Search code examples
cssflexbox

How can I setup a flexbox to wrap instead of expanding its parent's width?


I've looked through all the relevant questions and answers I could find, but none seem to apply to exactly this situation.

In my code below, the width of div 'side' keeps expanding to accommodate sideB's growing content. I want sideB and side to remain capped at the minimum, unwrapped width of sideA, leaving more space for main.

#top {
  display: flex;
  flex-direction: row;
  background-color: black;
  height: 100%;
}

#side {
  display: flex;
  flex-direction: column;
  background-color: red;
  height: 100%;
}

#sideA {
  flex-wrap: nowrap;
  white-space: nowrap;
  background-color: green;
}

#sideB {
  display: flex;
  flex-direction: row;
  flex-shrink: 10;
  flex-wrap: wrap;
  background-color: orange;
  gap: 4px;
}

#main {
  background-color: yellow;
  flex-grow: 100;
  height: 100%;
}

<div id="top">
  <div id="side">
    <div id="sideA">
      Content here should expand side.
    </div>
    <div id="sideB">
      This area should not grow wider than sideA's minimum, unwrapped width.
      <button>One button</button>
      <button>Another one</button>
      <button>Here's a third</button>
      <button>And finally this one</button>
    </div>
  </div>
  <div id="main">
    This content should fill up the width not required by sideA. While side should take up exactly the width of sideA, and sideB should just wrap as needed.
    <br/><br/><br/><br/><br/><br/><br/>
    <br/><br/><br/><br/><br/><br/><br/>
  </div>
</div>

Here's a runnable jsfiddle showing my issue: https://jsfiddle.net/6Lkbmq0e/

Thanks for any help you can provide!


Solution

  • Is there a reason you are set on flexbox? If not, I would strongly consider using CSS grid for your use case. While flexbox can kinda support a two-dimensional layout through wrapping, it's not what it excels at. Grid on the other hand is built for this and allows direct and granular control.

    Here's some grid-based CSS that achieves what you want, I believe:

    #top {
      display: grid;
      grid-template-columns: min-content 1fr;
      height: 100%;
      background-color: black;
    }
    
    #side {
      height: 100%;
      background-color: red;
    }
    
    #sideA {
      white-space: nowrap;
      background-color: green;
    }
    
    #sideB {
      display: flex;
      flex-wrap: wrap;
      gap: 4px;
      background-color: orange;
    }
    
    #main {
      height: 100%;
      background-color: yellow;
    }
    

    This uses #top to create a very basic two column layout: the first column shrinks as much as possible given the content, and the second column grows to fill the rest of the width. Note that #sideB may still use flexbox to layout its content.