-2

I am trying to create a flexbox with 3 items in it that are equal of width. The problem is if I add padding or gap or both. It breaks (only 2 columns)! I do not want to use grid. It needs to be flex!

This is the Html and css

.flex-container {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.color {
    background-color: limegreen;
}
.spacing {
    padding: 1em;
}
.flex-item {
    flex: calc(100% / 3);
}
<div class="flex-container">
    <div class="flex-item color spacing">1</div>
    <div class="flex-item color spacing">2</div>
    <div class="flex-item color spacing">2</div>
    <div class="flex-item color spacing">4</div>
    <div class="flex-item color spacing">5</div>
    <div class="flex-item color spacing">6</div>
    <div class="flex-item color spacing">7</div>
    <div class="flex-item color spacing">8</div>
</div>
Dai
  • 141,631
  • 28
  • 261
  • 374
Steve
  • 1
  • 3

4 Answers4

1

Just add following to .flex-item

flex: calc((100% - 2rem) / 3);
box-sizing: border-box; 

- 2rem is becuase you have gap between first and second and second and third element.

Thus, your code should be as follows:

.flex-container {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.color {
    background-color: limegreen;
}
.spacing {
    padding: 1em;
}
.flex-item {
  flex: calc((100% - 2rem) / 3);
  box-sizing: border-box; 
}
<div class="flex-container">
    <div class="flex-item color spacing">1</div>
    <div class="flex-item color spacing">2</div>
    <div class="flex-item color spacing">2</div>
    <div class="flex-item color spacing">4</div>
    <div class="flex-item color spacing">5</div>
    <div class="flex-item color spacing">6</div>
    <div class="flex-item color spacing">7</div>
    <div class="flex-item color spacing">8</div>
</div>

And if you want that the last two divs take only first and second column use then width instead of flex in .flex-item.

.flex-item {
  width: calc((100% - 2rem) / 3);
  box-sizing: border-box; 
}

Thus something as follows:

.flex-container {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}
.color {
    background-color: limegreen;
}
.spacing {
    padding: 1em;
}
.flex-item {
  width: calc((100% - 2rem) / 3);
  box-sizing: border-box; 
}
<div class="flex-container">
    <div class="flex-item color spacing">1</div>
    <div class="flex-item color spacing">2</div>
    <div class="flex-item color spacing">2</div>
    <div class="flex-item color spacing">4</div>
    <div class="flex-item color spacing">5</div>
    <div class="flex-item color spacing">6</div>
    <div class="flex-item color spacing">7</div>
    <div class="flex-item color spacing">8</div>
</div>
Boky
  • 11,554
  • 28
  • 93
  • 163
  • your calculation is a little off and is only corrected by `flex-grow` you need to subtract the gaps from the 100% before you divide it through 3. If you multiple your calculation with 3 you get a sum of `100% - 6rem` – tacoshy Oct 10 '22 at 11:56
  • @tacoshy You're right. Updated. – Boky Oct 10 '22 at 12:03
1

There are 2 things you need to do:

  1. Change the box-sizing of the flex-item to include the paddings by using: box-sizing: border-box
  2. Include the gap in the calculations. I recommend you to use a CSS-Variable for the gap: calc((100% - (2 * var(--gap))) / 3)

:root { 
  --gap: 1rem;
}

.flex-container {
  display: flex;
  flex-wrap: wrap;
  gap: var(--gap);
}

.color {
  background-color: limegreen;
}

.spacing {
  padding: 1em;
}

.flex-item {
  box-sizing: border-box;
  flex: calc((100% - (2 * var(--gap))) / 3);
}

.span-2 {
  flex: calc(((100% - (2 * var(--gap))) / 3) * 2 + var(--gap));
}
<div class="flex-container">
  <div class="flex-item color spacing">1</div>
  <div class="flex-item color spacing span-2">2</div>
  <div class="flex-item color spacing">2</div>
  <div class="flex-item color spacing">4</div>
  <div class="flex-item color spacing">5</div>
  <div class="flex-item color spacing">6</div>
  <div class="flex-item color spacing">7</div>
  <div class="flex-item color spacing">8</div>
</div>
tacoshy
  • 10,642
  • 5
  • 17
  • 34
  • Great, thanks! Love this. How would you move forward, if the first row for example needed to have 1 item occupy 1/3 of the space and the 2 item 2/3 of the space. Again not using grid. I try to understand what the possibilities of flex are. – Steve Oct 10 '22 at 12:42
  • add an additional class for the element that should span 2 columns by using `flex: calc(((100% - (2 * var(--gap))) / 3) * 2)` – tacoshy Oct 10 '22 at 12:48
  • Genius!! I added it but I notice now that the gap does not correctly align with the gap on the line beneath because I have 3 items there. How can I solve that? – Steve Oct 10 '22 at 13:00
  • Sorry, my mistake, I fogot to re-add 1 gap: `flex: calc(((100% - (2 * var(--gap))) / 3) * 2 + var(--gap))` – tacoshy Oct 10 '22 at 13:07
  • Yes!! works!! I added an extra class: flex: calc((100% - (5 * var(--gap))) / 6) - so the first line has now 2 items which each take 1/6 and than the 3th item takes up the rest of the space. I wonder now if it's possible to move the 3th item to the next line. Is this possible? – Steve Oct 10 '22 at 13:38
0

Make the padding/margin in an element inside the .flex-item

.flex-container {
  display: flex;
  flex-wrap: wrap;
}

.color {
  background-color: limegreen;
}

.spacing {
  margin: 1em;
}

.flex-item {
  flex: calc(100% / 3);
}
<div class="flex-container">
  <div class="flex-item"><div class="color spacing">1</div></div>
  <div class="flex-item"><div class="color spacing">2</div></div>
  <div class="flex-item"><div class="color spacing">2</div></div>
  <div class="flex-item"><div class="color spacing">4</div></div>
  <div class="flex-item"><div class="color spacing">5</div></div>
  <div class="flex-item"><div class="color spacing">6</div></div>
  <div class="flex-item"><div class="color spacing">7</div></div>
  <div class="flex-item"><div class="color spacing">8</div></div>
</div>
IT goldman
  • 14,885
  • 2
  • 14
  • 28
0

You can simply forbid padding from adding to the total width by adding this css

.flex-item {
  box-sizing: border-box;
}
Feyton
  • 27
  • 5
  • this fixes the paddings but not the gaps. – tacoshy Oct 10 '22 at 11:56
  • If you wish to add gaps you could account for them in the width dimensioning gap: 10px 3 gaps flex-item{ width: calc((100% / 3) - 3 * 10px) } – Feyton Oct 10 '22 at 12:33
  • that calculation is way off. The gap is 1rem. Then you have only 2 gaps in 3 columns. Last but not least you need to subtract the gaps from the 100% before you divide it by 3. – tacoshy Oct 10 '22 at 12:58