Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

html

css

flexbox

Is there a way to make a line break in multiple line flexbox?

For example to break after each 3rd item in this CodePen.

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

Like

.item:nth-child(3n){   /* line-break: after; */     } 
like image 989
Artem Svirskyi Avatar asked Apr 19 '15 16:04

Artem Svirskyi


People also ask

How do I add a new line in flexbox?

Inserting a line-breaking flex itemUsing an element to break to a new flex row comes with an interesting effect: we can skip specifying the width of any item in our flex layout and rely completely on the line breaks to define the flow of our grid.

How do you have content break to next line with flex when content reaches edge?

To have content break to next line with flex when content reaches edge with Flex React Native, we can set flexWrap to 'wrap' . to set flexDirection to 'row' to set the flexbox direction to horizontal. Then we set flexWrap to 'wrap' to make the child items wrap when it reaches the right edge of the screen.

How do I add spaces between flexbox items?

To set space between the flexbox you can use the flexbox property justify-content you can also visit all the property in that link. We can use the justify-content property of a flex container to set space between the flexbox.

Which flex property will you use to flex items on multiple lines?

The flex-wrap CSS property sets whether flex items are forced onto one line or can wrap onto multiple lines.


1 Answers

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>

But that's ugly and not semantic. Instead, we could generate pseudo-elements inside the flex container, and use order to move them to the right places.

.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(3n) {   background: silver; } .container::before, .container::after {   content: '';   width: 100%;   order: 1; } .item:nth-child(n + 4) {   order: 1; } .item:nth-child(n + 7) {   order: 2; }
<div class="container">   <div class="item">1</div>   <div class="item">2</div>   <div class="item">3</div>   <div class="item">4</div>   <div class="item">5</div>   <div class="item">6</div>   <div class="item">7</div>   <div class="item">8</div>   <div class="item">9</div> </div>

But there is a limitation: the flex container can only have a ::before and a ::after pseudo-element. That means you can only force 2 line breaks.

To solve that, you can generate the pseudo-elements inside the flex items instead of in the flex container. This way you won't be limited to 2. But those pseudo-elements won't be flex items, so they won't be able to force line breaks.

But luckily, CSS Display L3 has introduced display: contents (currently only supported by Firefox 37):

The element itself does not generate any boxes, but its children and pseudo-elements still generate boxes as normal. For the purposes of box generation and layout, the element must be treated as if it had been replaced with its children and pseudo-elements in the document tree.

So you can apply display: contents to the children of the flex container, and wrap the contents of each one inside an additional wrapper. Then, the flex items will be those additional wrappers and the pseudo-elements of the children.

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

Alternatively, according to an old version of the spec, Flexbox allowed forced breaks by using break-before, break-after or their old CSS 2.1 aliases:

.item:nth-child(3n) {   page-break-after: always; /* CSS 2.1 syntax */   break-after: always; /* CSS 3 syntax */ } 

But these forced line breaks only work on Firefox, and I don't think they are supposed to work according to the current spec. The new proposed way (not implemented anywhere) is with wrap-before or wrap-after:

.item:nth-child(3n) {   wrap-after: flex; /* New proposed syntax */ } 

.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(3n) {   page-break-after: always;   break-after: always;   wrap-after: flex;   background: silver; }
<div class="container">   <div class="item">1</div>   <div class="item">2</div>   <div class="item">3</div>   <div class="item">4</div>   <div class="item">5</div>   <div class="item">6</div>   <div class="item">7</div>   <div class="item">8</div>   <div class="item">9</div>   <div class="item">10</div> </div>
like image 109
Oriol Avatar answered Oct 10 '22 17:10

Oriol