Calculating flex-basis for items when the parent flex item uses gap

In CSS, how do you calculate flex-basis (or width) for items to make sure they fill the area they are supposed to, without using flex-grow.

This is one of those posts "for posterity" as I often come back to the thought of "what was my formula to do that"?

Let's say we have a grid of items, which are using flexbox for their layout. Let's say there are 3 items in a row, and we want them all to be 33.3333% wide with 2rem gap between each of the items.

What does this mean. It means we have a 3 elements in a row with a gap of 2rem between the first and second elements, and a gap of 2rem between the second and third element. So, with that being the case, we need width of three elements to be 100% minus 4rem, and each item to be one-third of that value.

Here's my CSS for that:

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 2rem;
}

.item {
  width: calc(100% / 3 - (2rem * 2 / 3));
}

I'm using width here instead of flex-basis, but you can use whichever one you want. Let's see what is happening here.

  1. We want each item to be one-third of the available space - 100% / 3. However, this will cause the last one to wrap to the next line (yes, I know we can remove flex-wrap, but this is just for illustration and with the thoughts of responsive design in my mind).
  2. Then we need to get the value of the gap (in my 'real' CSS each of these items would be a variable), in this case 2rem and we multiply it by the number of gaps we have - 2 (giving us 4rem) - we then divide that by the number of items in our row - 3. So, in effect we are saying that the gap per element is two-thirds of the specified gap value - two-thirds or 2rem. There will always be one gap fewer than there are items. 3-in-a-row, 2 gaps; 4-in-a-row, 3 gaps, etc.
  3. Finally, we need to make sure this second calculation is inside it's own brackets, so that it's calculated on it's own and the value of that calculation is taken away from the value of the first - 100% / 3 - calculation.

Let's see if we can get a little formula for this.

.container--3-in-row {
  --number-of-items: 3;
  --number-of-gaps: 2;
  display: flex;
  flex-wrap: wrap;
  gap: --gap;
}

.item {
  width: calc(100% / var(--number-of-items) - (var(--gap) * var(--number-of-gaps) / var(--number-of-items)));
}

 

Filed Under:

  1. CSS
  2. Flexbox