Flexbox space-between has extra 1px gap at the end when using calc()
The Problem
I played around with this problem a little bit before coming to a solution. The steps as follows:
First I converted everything to use a standard format
calc(a/12 * 100% - (7/6 - a/12) * 24px)
where a = "col number"
Next I began experimenting with the number to see the actual output without units (of course)
- 1: -17.6666...
- 2: -7.3333...
- 3: 3
- 4: 13.3333...
- 5: 23.6666...
- 6: 34
- 7: 44.3333...
- 8: 54.6666...
- 9: 65
- 10: 75.3333...
- 11: 85.6666...
- 12: 96
Form this we can see three things
- Any number divisible by 3 is a whole number
- The next number ends by repeating
x.3333...
- The second number ends in
x.6666...
Note: 1 and 2 are special cases and are reversed because their output is actually negative. We can assume that their numbers would be positive in the real world and would fall inline with the others
After that pinpointing the actual issue in the equation was easy:
a/12 * 100%
So the rounding issue is your problem - i.e. when you use two or more numbers ending in x.3333...
The Fix
We would like these rounding errors not to cascade so we have a few options
- Add an subtract the values to get some middle number
- Add some half pixel to decrease the error and hopefully round the issue away (only add half pixel to numbers ending in
x.3333...
)
Examples:
flex-basis: calc((8/12 - 1/6/100) * 100% - (7/6 - 8/12) * 24px);
flex-basis: calc(8/12 * 100% - (7/6 - 8/12) * 24px);
I went with the first example to give me this repeating code:
* {
margin: 0;
padding: 0;
}
.row {
display: flex;
flex-wrap: wrap;
max-width: 550px;
width: 100%;
margin: 0 auto;
border: 2px solid #888;
justify-content: space-between;
}
div[class^="col"] {
border: 2px solid red;
}
.col-12 {
flex-basis: calc(12/12 * 100% - (7/6 - 12/12) * 24px);
}
.col-11 {
flex-basis: calc((11/12 - 1/6/100) * 100% - (7/6 - 11/12) * 24px);
}
.col-10 {
flex-basis: calc((10/12 + 1/6/100) * 100% - (7/6 - 10/12) * 24px);
}
.col-9 {
flex-basis: calc(9/12 * 100% - (7/6 - 9/12) * 24px);
}
.col-8 {
flex-basis: calc((8/12 - 1/6/100) * 100% - (7/6 - 8/12) * 24px);
}
.col-7 {
flex-basis: calc((7/12 + 1/6/100) * 100% - (7/6 - 7/12) * 24px);
}
.col-6 {
flex-basis: calc(6/12 * 100% - (7/6 - 6/12) * 24px);
}
.col-5 {
flex-basis: calc((5/12 - 1/6/100) * 100% - (7/6 - 5/12) * 24px);
}
.col-4 {
flex-basis: calc((4/12 + 1/6/100) * 100% - (7/6 - 4/12) * 24px);
}
.col-3 {
flex-basis: calc(3/12 * 100% - (7/6 - 3/12) * 24px);
}
.col-2 {
flex-basis: calc((2/12 - 1/6/100) * 100% - (7/6 - 2/12) * 24px);
}
.col-1 {
flex-basis: calc((1/12 + 1/6/100) * 100% - (7/6 - 1/12) * 24px);
}
<div class="row">
<div class="col-12">col-12</div>
<div class="col-6">col-6</div>
<div class="col-6">col-6</div>
<div class="col-4">col-4</div>
<div class="col-4">col-4</div>
<div class="col-4">col-4</div>
<div class="col-3">col-3</div>
<div class="col-3">col-3</div>
<div class="col-6">col-6</div>
<div class="col-3">col-3</div>
<div class="col-3">col-3</div>
<div class="col-3">col-3</div>
<div class="col-3">col-3</div>
<div class="col-4">col-4</div>
<div class="col-8">col-8</div>
<div class="col-7">col-7</div>
<div class="col-5">col-5</div>
<div class="col-6">col-6</div>
<div class="col-4">col-4</div>
<div class="col-2">col-2</div>
</div>
This should work in modern and even most older browsers that support non-rounded calc
If you would like to see the second solution just leave a comment and I'll post it.
Note: if you can it would be best to use a language like sass or less to perform these calculations as they after rounding and also functions to keep all this hard work in one place.