Should Flex Item Overflow the Flex Container Instead of Breaking Lines

Should flex item overflow the flex container instead of breaking lines?

This is what happens:

  1. The Line Length Determination algorithm determines that the flex base size of the flex item is its max-content

    Size the item into the available space using its used flex
    basis in place of its main size, treating a value of
    content as max-content. [...] The flex base size is
    the item’s resulting main size.

  2. Since there are no min nor max size constraints, the hypothetical main size of the flex item is the same value

    The hypothetical main size is the item’s flex base size
    clamped according to its min and max main size properties.

  3. The Resolving Flexible Lengths algorithm freezes the inflexible flex item and sets its target main size to its hypothetical main size

    Size inflexible items. Freeze, setting its target main size to its
    hypothetical main size any item that has a flex factor of zero

  4. Finally, the main size is that value too:

    Set each item’s used main size to its target main size.

Therefore, your flex item should be sized as if it had flex-basis: max-content. Chrome, Edge and IE do it correctly.

Instead, Firefox seems to size as if it had flex-basis: fit-content. IMO this is more reasonable, but it's not standard. Bug 876985 should fix this.

Meanwhile, to achieve the standard behavior on Firefox you can use

flex-basis: -moz-max-content;

.flex-container {  display: flex;  width: 175px;  border: 3px solid black;  margin-bottom: 10px;}.flex-item {  flex: none;  flex-basis: -moz-max-content;  border: 3px solid blue;  margin: 3px;}.box {  display: inline-block;  vertical-align: middle;  width: 100px;  height: 100px;  border: 3px solid red;  margin: 3px;}
<div class="flex-container">  <div class="flex-item">    <div class="box"></div>    <div class="box"></div>  </div></div>

How to specify line breaks in a multi-line flexbox layout?

The simplest and most reliable solution is inserting flex items at the right places. If they are wide enough (width: 100%), they will force a line break.

.container {
background: tomato;
display: flex;
flex-flow: row wrap;
align-content: space-between;
justify-content: space-between;
}
.item {
width: 100px;
background: gold;
height: 100px;
border: 1px solid black;
font-size: 30px;
line-height: 100px;
text-align: center;
margin: 10px
}
.item:nth-child(4n - 1) {
background: silver;
}
.line-break {
width: 100%;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="line-break"></div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="line-break"></div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="line-break"></div>
<div class="item">10</div>
</div>

Prevent flex items from overflowing a container

Your flex items have

flex: 0 0 200px; /* <aside> */
flex: 1 0 auto; /* <article> */

That means:

  • The <aside> will start at 200px wide.

    Then it won't grow nor shrink.

  • The <article> will start at the width given by the content.

    Then, if there is available space, it will grow to cover it.

    Otherwise it won't shrink.

To prevent horizontal overflow, you can:

  • Use flex-basis: 0 and then let them grow with a positive flex-grow.
  • Use a positive flex-shrink to let them shrink if there isn't enough space.

To prevent vertical overflow, you can

  • Use min-height instead of height to allow the flex items grow more if necessary
  • Use overflow different than visible on the flex items
  • Use overflow different than visible on the flex container

For example,

main, aside, article {
margin: 10px;
border: solid 1px #000;
border-bottom: 0;
min-height: 50px; /* min-height instead of height */
}
main {
display: flex;
}
aside {
flex: 0 1 200px; /* Positive flex-shrink */
}
article {
flex: 1 1 auto; /* Positive flex-shrink */
}
<main>
<aside>x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x </aside>
<article>don't let flex item overflow container.... y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y y </article>
</main>

prevent line wrap between certain flex child elements

Treat every pair of elements—(A,B), (C,D), (E,F)—as a separate flex item to ensure they wrap into flex lines together. Or use grid layout for a simpler solution.

Flexbox solution

Every time you resize the flex container, the flex container will try to figure out how many flex items can fit into any given line. Each element (A, B, C, etc.) is evaluated separately for this purpose, which means that one element in a pair might fit into a flex line, and the other may wrap into the next line.

To ensure these pairs wrap together, you could wrap each pair into another element. That way your flex container doesn’t see individual elements as flex items anymore (A, B, C, D, and so on). Instead, it will see pairs as flex items (AB, CD, EF). Then each pair element can be a flex container itself to make sure the elements inside are laid out horizontally.

<div style="resize: horizontal; overflow: hidden; border: 10px solid black">
<div style="display: flex; flex-wrap: wrap">
<div class="flex-item" style="flex: none; display: flex">
<div style="width: 100px; border: 10px solid #f77">A</div>
<div style="width: 20px; border: 10px solid #373">B</div>
</div>
<div class="flex-item" style="flex: none; display: flex">
<div style="width: 100px; border: 10px solid #f77">C</div>
<div style="width: 20px; border: 10px solid #373">D</div>
</div>
<div class="flex-item" style="flex: none; display: flex">
<div style="width: 100px; border: 10px solid #f77">E</div>
<div style="width: 20px; border: 10px solid #373">F</div>
</div>
</div>
</div>

Flexbox item wrap to a new line

If you look at this great answer you'll notice that the only cross-browser way (without 2 line break limit) is inserting 100%-width empty blocks ("line-breaks"). So for similar markup this will look like

.flex {  display: flex;  flex-wrap: wrap;  border: 2px solid red;}
.item { width: 50px; height: 50px; margin: 5px; border: 2px solid blue;}
.line-break { width: 100%;}
<div class="flex">  <div class="item"></div>  <div class="item"></div>  <div class="item"></div>  <div class="line-break"></div>  <div class="item"></div>  <div class="item"></div>  <div class="line-break"></div>  <div class="item"></div>  <div class="line-break"></div>  <div class="item"></div>  <div class="item"></div>  <div class="item"></div></div>

Equal size of flex item while breaking the last item to next line

You should set flex-grow:0 and should be calc(100% / 6) instead of calc(100% / 7). Also I added box-sizing:border-box; for borders to be included in width.

ul {  padding: 0;  margin: 0;  list-style-type: none;  display: flex;  flex-flow: row wrap;}
li { flex: 1; border: solid 1px; text-align: center; flex-basis: calc(100% / 6); box-sizing: border-box;}
.keep-next-line { flex-grow: 0;}
<ul>  <li>1</li>  <li>2</li>  <li>3</li>  <li>4</li>  <li>5</li>  <li>6</li>  <li class="keep-next-line">7</li>  <!--Kepp this next line, but size should be equal to other item--></ul>

Why do flex items wrap instead of shrink?

The flex-shrink property often comes in handy in a single-line flex container (flex-wrap: nowrap).

In other words, when the flex items cannot wrap, flex-shrink will enable them to shrink when the container is too small (the spec calls this negative free space). This has the effect of preventing flex items from overflowing the container.

However, in a multi-line flex container (flex-wrap: wrap) no negative free space is created most of the time because flex items can create additional lines. An exception is when a multi-line container in, let's say, row-direction, is narrow enough to wrap all items. This leaves items stacked in a single column. Now they will shrink or hold firm, depending on flex-shrink (demo).

You have a row-direction, wrap-enabled flex container with three flex items.

  • div #1 ~ flex: 1 0 200px
  • div #2 ~ flex: 1 1 400px
  • div #3 ~ flex: 1 0 200px

When the container is greater than 800px, all items stay on the line.

When the container breaks below 800px, div #3 will wrap (there is no need to shrink, even if it could).

At the 600px mark (the combined width of divs #1 & #2), div #2 wraps. Again, no need to shrink.

#container {  display: flex;  flex-direction: row;  flex-wrap: wrap;}div:nth-child(1) {  flex: 1 0 200px;  height: 200px;  background-color: lightgreen;}div:nth-child(2) {  flex: 1 1 400px;  height: 200px;  background-color: lightyellow;}div:nth-child(3) {  flex: 1 0 200px;  height: 200px;  background-color: lightblue;}
<div id="container">  <div></div>  <div></div>  <div></div></div>


Related Topics



Leave a reply



Submit