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
- ul list of some related items
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>
CodePudding user response:
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;
}