6

I am constructing a form where the field's width percentage is dynamically set by clients. My first approach was to create a flex container with wrapping enabled and space the fields evenly using gap: 16px. To my surprise, flex-wrap and gap don't behave as I would expect.

main {
  width: 400px;
  background-color: gray;
  
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
}

div {
  background-color: blue;
}

.first {
  width: 50%;
}

.second {
  width: 50%;
}
<main>
  <div class="first">First</div>
  <div class="second">Second</div>
</main>

I expected them to be in the same line and have the gap in-between. This happens when I remove the flex-wrap.

The only solution I found was to use calc(50% - 16px), but this is far from ideal. Maybe I'm approaching the problem wrongly?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Víctor Navarro
  • 812
  • 9
  • 12
  • 3
    50% + 50% + 16px > 100% – Temani Afif Feb 17 '21 at 10:55
  • But this is not the case when `flex-wrap: nowrap` – Víctor Navarro Feb 17 '21 at 10:58
  • 3
    I was expecting 50% = (100% - 16px) / 2 – Víctor Navarro Feb 17 '21 at 11:00
  • no, width:50% means half the width, gap is not involved there. When you don't allow the wrap, it's a different story and the shrink factor will enter in play (add flex-shrink:0 and you will have an overflow with nowrap) – Temani Afif Feb 17 '21 at 11:05
  • 1
    This question is not a duplicate. The question how to work with percentage boxes, gap and flex is not given in https://stackoverflow.com/questions/20626685/better-way-to-set-distance-between-flexbox-items/27563449#27563449 – Adam May 10 '22 at 11:11
  • Does this answer your question? [CSS Flexbox Gap - gap value affecting width calculation](https://stackoverflow.com/questions/68007483/css-flexbox-gap-gap-value-affecting-width-calculation) – 0stone0 May 12 '22 at 12:53

1 Answers1

0

This post has the answer. https://wiryawanadipa.com/blog/calculate-percentage-width-of-flex-items-when-using-gap/

The solution is a formula based in the amount of items per row and the size of the gap:

width: calc((100% / n) - (((n - 1) / n) * g));

where [n = Number of items per row] and [g = Size of gap]

:root {
    --flex-gap: 1rem; /* Variable for gap */
}

*,
*::after,
*::before {
    box-sizing: border-box;
}
.container {
  display: flex;
  flex-wrap: wrap;
  gap: var(--flex-gap);
}
.item {
  --flex-items: 1; /* Variable for number of items */
  width: calc((100% / var(--flex-items)) - (((var(--flex-items) - 1) / var(--flex-items)) * var(--flex-gap)));
  padding: 3rem 1rem;
  background-color: #999;
  color: white;
  font-size: 28px;
  text-align: center;
}
@media (min-width: 520px) {
  .item {
    --flex-items: 2; /* Variable for number of items */
  }
}
@media (min-width: 768px) {
  .item {
    --flex-items: 3; /* Variable for number of items */
  }
}
@media (min-width: 1200px) {
  .item {
    --flex-items: 4; /* Variable for number of items */
  }
}
<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
</div>
Tamplix
  • 53
  • 1
  • 7