Áxel Costas Pena
Áxel Costas Pena

Reputation: 6235

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:

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>

Upvotes: 0

Views: 1260

Answers (2)

AREA CREW BMX
AREA CREW BMX

Reputation: 1

* {
    /* just for reset and for remove all margins and paddings */
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

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; */
    max-width: fit-content; 
    /* is like 488px, but is resizable*/
    /* you wrong, the ul by default doesn't 
    push to next line any elements, 
    you have did a static width 
    of maximum 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>

You have did a "static" width on 2nd child of max(250px) and then, they can't wrap anymore beacuse they were already wrapped.

Upvotes: 0

Godnyl Pula
Godnyl Pula

Reputation: 115

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;
}

Upvotes: 1

Related Questions