19

Take a look at this example

It has a flexbox container with flex-flow: row wrap; to wrap all items. This is almost what I want.

When it starts to wrap, item number 6 wraps to the second line:

1 2 3 4 5
    6

But always I want to wrap at least two items when it starts to wrap so you'll never have a single items on a line:

1 2 3 4
  5 6
Jayne Mast
  • 1,427
  • 1
  • 16
  • 32
  • 1
    Fun fact: in typography, when the last word of a sentence is wrapped to to the next line, it’s called an “orphan.” In Dutch, this is “hoerenjong.” This is basically the issue, yes? – Tim S. May 22 '15 at 08:52
  • Yes, that's the problem. I do know CSS has orphans, but that only works on text like you said. Would be great if it would work on flex blocks. PS. Nice fact about the Dutch word, did not know that. We are weird. – Jayne Mast May 22 '15 at 08:58
  • 1
    I can remember this was discussed for a future flexbox level on some mailing list (didn’t find a link to it) and so far I can’t see an option to adjust the wrap with current flexbox options/properties,values. – helloanselm May 22 '15 at 09:05
  • Interesting conversation. Actually it seems to be rather a "widow", "orphans" are at the beginning. This lead me to this interesting page : http://demosthenes.info/blog/946/CSS-last-line-Controlling-Widows-&-Orphans but I could not get anything working in the codepen: http://codepen.io/Olivvv/pen/KpgeWV – Olivvv May 22 '15 at 09:15

5 Answers5

2

While not the most elegant solution, you could wrap the last two elements in another flexbox:

<html>
    <head>
        <style>
            .flex {
                display: flex;
                flex-wrap: wrap;
            }
            .flex > div {
                flex: 1 0 auto;
                padding: 20px;
                text-align: center;
            }
            .flex .flex {
                padding: 0;
                flex-grow: 2;
            }
        </style>
    </head>
    <body>
        <div class="flex">
            <div>1</div>
            <div>2</div>
            <div>3</div>
            <div>4</div>
            <div class="flex">
                <div>5</div>
                <div>6</div>
            </div>
        </div>
    </body>
</html>

See a pen here: https://codepen.io/anon/pen/prodVd

Rolf
  • 41
  • 3
  • 1
    That kind of removes the whole flexible part from flexbox – Jayne Mast Jul 24 '17 at 11:58
  • You could try to inject the second flex-container with js. As I said, not elegant, but it seems to work. I'd love to see a better, pure CSS solution, though. – Rolf Jul 24 '17 at 20:28
  • This has a drawback: you can get the situation when 1 2 3 - at the first line; 4 - at the second line; 5 6 - at the third line; because 4 and 5&6 don't fit into one line – karagota Nov 25 '20 at 07:34
1

I figured out a way to do it for inline Elements, however it will behave inconsistently across browsers when used with inline-blocks. Still not a solution, but maybe somebody can figure out a way to make it behave with inline-block elements.

.item {
  display: inline;
}

.item::before {
  content: ' ';
  font-size: 0;
}

.item:last-child::before {
  content: '';
}

Here is a Fiddle with it in action.

Nuvanda
  • 474
  • 4
  • 14
  • That's a very interesting solution. Not sure if it worked for my old case (because it was 2 years ago), but it does what I asked for. – Jayne Mast Jul 31 '17 at 06:17
0

Here's an approach that should work under the constraint that the width of the element is fixed

Assuming the width is 50px:

.container {
  display: flex;
  flex-flow: row wrap; 
}

.flex-item: {
  width: 50px;
  display: block;
}

.flex-item:nth-child(even) {
  translateX(100%)
  margin-left: -100px;
}

.flex-item:nth-child(odd) {
  margin-right: 50px;
}

The trick is to basically move the "footprint" of every 2nd element into its predecessor (negative margin), still display it in its original place (translate) and having the predecessor eat the remaining space (positive margin) for the purpose of row-breaking.

the8472
  • 40,999
  • 5
  • 70
  • 122
0

You can try to wrap 2 sibling elements with flex container

Ivan Frolov
  • 103
  • 6
0

Based on https://stackoverflow.com/a/30431565/6884587 which did not work due to syntactical and logical reasons, I figured out how to do it for preknown same width items.

.container {
  display: flex;
  flex-flow: row wrap; 
  justify-content: center;
  /* gap: 5px <-- can be used for spacing */
}

.flex-item: {
  width: 50px;
  display: block;
}

.flex-item:last-child {
  margin-left: -50px; /* consider gap in this value, if applicable */
}

.flex-item:nth-last-child(2) {
  margin-right: 50px; /* consider gap in this value, if applicable */}

This way, the last and the next to last item literally end on the same pixel, causing them to wrap line together.

For not preknown, but same width items it is a little more complex, since setting the margin to a percentage value is based on the item parent's width.

Creepin
  • 482
  • 4
  • 20