How to inline+wrap elements and their children in a flex container?

I need to display some elements inline so they wrap when they fill the viewport width. I’d prefer to use flex with – easy and maintainable, gap clearly defined – instead of inline or floats – you need to use margins for the gap, then avoid ugly wraps using negative margin…

Problem is I am not being able to do it when the items to align are nested on different parents. Example of the tags I’d like to align:

  • div wrapper:
    • ul list of some related items
      • li item
      • li item
    • span item not in list
    • span item not in list

I am attaching a demo, where the structgure is repeated 3 times, each time offering less width to showcase how the items wrap. The ul behaves perfectly as an inline element, until it has to wrap, then it behaves as a block element.

div {
    border: 1px solid blue; /* for easier debugging */
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    margin-bottom: 40px; /* just visual separation between the 3 examples */
}

div:nth-of-type(2) {
    max-width: 450px; /* stretcher just to show how items wrap */
}

div:nth-of-type(3) {
    max-width: 250px; /* stretcher just to show how items wrap */
}

ul {
    border: 1px solid green; /* for easier debugging */
    display: inline-flex;
    flex-wrap: wrap;  
    gap: 20px;
}

li, span {
    border: 1px solid red; /* for easier debugging */
    display: inline;
}
<div>
  <ul>
    <li>Option 1</li>
    <li>Option 2</li>
    <li>Option 3</li>
  </ul>
  <span>Action 1</span>
  <span>Action 2</span>
  <span>Action 3</span>
</div>

<!-- structure repeats 3 times -->

<p>This wraps okay</p>
<div>
  <ul>
    <li>Option 1</li>
    <li>Option 2</li>
    <li>Option 3</li>
  </ul>
  <span>Action 1</span>
  <span>Action 2</span>
  <span>Action 3</span>
</div>

<p>The UL pushed next inline elements to a new line :(</p>
<div>
  <ul>
    <li>Option 1</li>
    <li>Option 2</li>
    <li>Option 3</li>
  </ul>
  <span>Action 1</span>
  <span>Action 2</span>
  <span>Action 3</span>
</div>

>Solution :

Use the display: contents property on the ul element, which allows the child elements to be treated as if they were direct children of the parent container.

ul {
    display: contents;
}

Can also use display: inline-block on the li and span elements instead of display: inline which allow them to have their own layout. Also you can use white-space: nowrap on the ul to prevent it from breaking to a new line.

li, span {
    display: inline-block;
}

ul {
    white-space: nowrap;
}

Leave a Reply