I have a container with multiple flex elements inside, separated by a gap
. These elements wrap within the container, and have a percentage-based size dictating how many can appear in a single row (ie, 4 per row = 25%).
Now, because the percentage-based size doesnt take into account the gap size, we must use a formula to determine the size of the elements, taking into account the gap we need (taken from here):
calc((100% / var(--flex-items)) - (((var(--flex-items) - 1) / var(--flex-items)) * var(--flex-gap)));
This works fine and well, an is easily adaptable for different amount of flex objects per row. But the issue comes in when changing the value of the gap
, while transitioning it.
While the appearance before and after the transition appear as they should, during the transition, the calculation is for some reason, not being made correctly, and so one more item wraps than should, until settling into how it should look after the appearance. This only happens when DECREASING the value of gap
— it animates as expected when increasing the gap
What is happening the during the animation between the 2 values that is causing the width calculation / gap value to not be in sync?
Codepen
$( "body" ).on( "click", function() {
$(".flexbox").toggleClass("bigger");
} );
:root {
--flex-gap: 1rem;
}
.flexbox {
display: flex;
flex-wrap: wrap;
gap: var(--flex-gap);
justify-content: center;
transition: gap 0.5s;
}
.flexbox.bigger {
--flex-gap: 3rem;
}
.flex-items {
--flex-items: 4;
aspect-ratio: 2 / 1;
display: flex;
background: red;
flex: 1 1 calc((100% / var(--flex-items)) - (((var(--flex-items) - 1) / var(--flex-items)) * var(--flex-gap)));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<html>
<body>
<div class="flexbox">
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
<div class="flex-items"></div>
</div>
</body>
</html>
2
Answers
I suspect the problem lies with a sort of edge effect with the widths being calculated, there may be some point at which part CSS pixels don’t quite fit within the actual screen pixels (tho’ I’m not certain).
However, switching to grid overcomes the problem.
You need to apply a transition to the
flex-basis
on the flex items as well.