skip to Main Content

Using CSS grid or flexbox, I want to achieve the following responsive layout:

  1. Try to lay out two items as equal width columns.
  2. If that’s not possible because one of the items’ content is too long then the items should wrap onto separate rows. The text should not wrap.

As a basis, below are two reduced test cases: one that uses CSS grid and one that uses CSS flexbox. As you can see, the items correctly appear as equal width columns when the content is short enough (1), but I have been unable to make the items wrap when the content is too long (2).

I was hoping this would be possible using some combination of the following:

  • grid-template-columns and repeat(auto-fit, …) or repeat(auto-fill, …)
  • minmax
  • min-content/max-content

… but so far I have been unable to find a solution that works.

If possible I would like to avoid using percentages because these are not inclusive of the grid/flex gap.

Grid

.container {
  border: 1px solid black;
  width: 500px;

  display: grid;
  gap: 20px;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
}

.item {
  border: 1px solid black;
  white-space: nowrap;
}
<h1>Expected result: items should be equal width columns (1) ✅</h1>
<div class="container">
  <div class="item">foo bar baz</div>
  <div class="item">foo bar baz</div>
</div>

<h1>Expected result: items should wrap (2) ❌</h1>
<div class="container">
  <div class="item">
    foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz
  </div>
  <div class="item">foo bar baz</div>
</div>

Flexbox

.container {
  border: 1px solid black;
  width: 500px;

  display: flex;
  gap: 20px;
  flex-wrap: wrap;
}

.item {
  border: 1px solid black;
  white-space: nowrap;

  flex-basis: 0;
  flex-grow: 1;
  flex-shrink: 0;
}
<h1>Expected result: items should be equal width columns (1) ✅</h1>
<div class="container">
  <div class="item">foo bar baz</div>
  <div class="item">foo bar baz</div>
</div>

<h1>Expected result: items should wrap (2) ❌</h1>
<div class="container">
  <div class="item">
    foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz
  </div>
  <div class="item">foo bar baz</div>
</div>

2

Answers


  1. I don’t think you will be able to do this without precentage.

    .container {
      border: 1px solid black;
      width: 500px;
    
      display: flex;
      gap: 20px;
      flex-wrap: wrap;
    }
    
    .item {
      border: 1px solid black;
      width: 50%;
      flex-basis: 0;
      flex-grow: 1;
      flex-shrink: 0;
    }
    <h1>Expected result: items should be equal width columns (1) ✅</h1>
    <div class="container">
      <div class="item">foo bar baz</div>
      <div class="item">foo bar baz</div>
    </div>
    
    <h1>Expected result: items should wrap (2) ❌</h1>
    <div class="container">
      <div class="item">
        foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz
      </div>
      <div class="item">foo bar baz</div>
    </div>
    Login or Signup to reply.
  2. Define a flex-basis equal to 50% (considering the gap)

    .container {
      --g: 20px;
      border: 1px solid black;
      width: 500px;
    
      display: flex;
      gap: var(--g);
      flex-wrap: wrap;
    }
    
    .item {
      border: 1px solid black;
      box-sizing: border-box;
      white-space: nowrap;
    
      flex-basis: calc(50% - var(--g)/2);
      flex-grow: 1;
      flex-shrink: 0;
    }
    <h1>Expected result: items should be equal width columns (1) ✅</h1>
    <div class="container">
      <div class="item">foo bar baz</div>
      <div class="item">foo bar baz</div>
    </div>
    
    <h1>Expected result: items should wrap (2) ❌</h1>
    <div class="container">
      <div class="item">
        foo bar baz foo bar baz foo bar baz foo bar baz foo bar baz
      </div>
      <div class="item">foo bar baz</div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search