如何在多行flexbox布局中指定换行符?

有一种方法使换行在多行flexbox?

例如,在这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>

就像

.item:nth-child(3n){
/* line-break: after; */
}
487260 次浏览

最简单、最可靠的解决方案是在正确的位置插入伸缩件。如果它们足够宽(width: 100%),它们将强制换行。

.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>

但这是丑陋的,也不是语义上的。相反,我们可以在flex容器内生成伪元素,并使用order将它们移动到正确的位置。

.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>

但是有一个限制:flex容器只能有::before::after伪元素。这意味着你只能强制2个换行符。

要解决这个问题,您可以在伸缩项中而不是在伸缩容器中生成伪元素。这样你就不会被限制在2个。但是这些伪元素不是伸缩项,所以它们不能强制换行。

但幸运的是,CSS显示L3引入了display: contents(目前仅由Firefox 37支持):

元素本身不生成任何方框,但是它的子元素和 伪元素仍然会正常生成方框。为了 框生成和布局时,必须将元素视为已存在 已替换为文档中的子元素和伪元素 树。< / p >

因此,你可以将display: contents应用于伸缩容器的子容器,并将每个子容器的内容包装在一个额外的包装器中。然后,伸缩项将是那些额外的包装器和子元素的伪元素。

.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>

另外,根据旧版本的规范, Flexbox允许使用break-beforebreak-after或它们的旧css2.1别名强制中断:

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

但是这些强制换行只在Firefox上工作,并且我不认为它们应该根据当前的规范工作。新提议的方法(没有在任何地方实现)是__ABC0或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>

对于将来的问题,也可以通过使用float属性并在每个3个元素中清除它来实现。

我举了一个例子。

.grid {
display: inline-block;
}


.cell {
display: inline-block;
position: relative;
float: left;
margin: 8px;
width: 48px;
height: 48px;
background-color: #bdbdbd;
font-family: 'Helvetica', 'Arial', sans-serif;
font-size: 14px;
font-weight: 400;
line-height: 20px;
text-indent: 4px;
color: #fff;
}


.cell:nth-child(3n) + .cell {
clear: both;
}
<div class="grid">
<div class="cell">1</div>
<div class="cell">2</div>
<div class="cell">3</div>
<div class="cell">4</div>
<div class="cell">5</div>
<div class="cell">6</div>
<div class="cell">7</div>
<div class="cell">8</div>
<div class="cell">9</div>
<div class="cell">10</div>
</div>

.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;
}
<div class="container">
<div>
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
<div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
<div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
<div class="item">10</div>
</div>

您可以尝试将项目包装在像这样的dom元素中。有了这个,你不需要知道很多CSS只是有一个良好的结构将解决问题。

@Oriol有一个很好的答案,遗憾的是,截至2017年10月,display:contentspage-break-after都没有得到广泛支持,更好地说,这是关于Firefox的支持,但不支持其他播放器,我想出了以下“hack”;我认为这比在每第三个元素之后进行硬编码要好,因为那样会使页面很难移动友好。

正如所说,这是一个黑客,缺点是你需要添加相当多的额外元素,但它做到了技巧,即使在过时的IE11上也能跨浏览器工作。

“hack"是简单地在每个div后面添加一个额外的元素,该元素被设置为display:none,然后使用css nth-child来决定哪个元素应该实际可见,并像这样强制行制动:

.container {
background: tomato;
display: flex;
flex-flow: row wrap;
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-1) {
background: silver;
}
.breaker {
display: none;
}
.breaker:nth-child(3n) {
display: block;
width: 100%;
height: 0;
}
<div class="container">
<div class="item">1</div>
<p class="breaker"></p>
  

<div class="item">2</div>
<p class="breaker"></p>
  

<div class="item">3</div>
<p class="breaker"></p>
  

<div class="item">4</div>
<p class="breaker"></p>
  

<div class="item">5</div>
<p class="breaker"></p>
  

<div class="item">6</div>
<p class="breaker"></p>
  

<div class="item">7</div>
<p class="breaker"></p>
  

<div class="item">8</div>
<p class="breaker"></p>
  

<div class="item">9</div>
<p class="breaker"></p>
  

<div class="item">10</div>
<p class="breaker"></p>
</div>

我认为传统的方式比较灵活,也比较容易理解:

标记

<div class="flex-grid">
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>


<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>
<div class="col-4">.col-4</div>


<div class="col-3">.col-3</div>
<div class="col-9">.col-9</div>


<div class="col-6">.col-6</div>
<div class="col-6">.col-6</div>
</div>

创建css文件:

.flex-grid {
display: flex;
flex-flow: wrap;
}


.col-1 {flex: 0 0 8.3333%}
.col-2 {flex: 0 0 16.6666%}
.col-3 {flex: 0 0 25%}
.col-4 {flex: 0 0 33.3333%}
.col-5 {flex: 0 0 41.6666%}
.col-6 {flex: 0 0 50%}
.col-7 {flex: 0 0 58.3333%}
.col-8 {flex: 0 0 66.6666%}
.col-9 {flex: 0 0 75%}
.col-10 {flex: 0 0 83.3333%}
.col-11 {flex: 0 0 91.6666%}
.col-12 {flex: 0 0 100%}


[class*="col-"] {
margin: 0 0 10px 0;


-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}


@media (max-width: 400px) {
.flex-grid {
display: block;
}
}

我已经创建了一个示例(jsfiddle)

试着将窗口大小调整到400px以下,它是有响应的!!

从我的角度来看,在伸缩项之间使用<hr> 元素作为换行符更具语义性。

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


.container hr {
width: 100%;
}
<div class="container">
<div>1</div>
<div>2</div>
<hr>
<div>3</div>
<div>2</div>
...
</div>

在Chrome 66, Firefox 60和Safari 11中测试。

你想要语义换行?

然后考虑使用<br>。W3Schools可能会建议你BR只是用来写诗的(我的很快就会来),但你可以改变风格,让它表现为一个100%宽度的块元素,将你的内容推到下一行。如果'br'建议一个断点,那么对我来说,它似乎比使用hr或100% div更合适,并使html更具可读性。

在需要换行符的地方插入<br>,并像这样设置它的样式。

 // Use `>` to avoid styling `<br>` inside your boxes
.container > br
{
width: 100%;
content: '';
}

你可以通过适当地将display:设置为blocknone使用媒体查询禁用<br>(我已经包含了一个这样的例子,但省略了注释)。

如果需要,也可以使用order:来设置顺序。

你可以放很多你想要的,用不同的类或名字:-)

.container {
background: tomato;
display: flex;
flex-flow: row wrap;
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
}


.container > br
{
width: 100%;
content: '';
}


// .linebreak1
// {
//    display: none;
// }


// @media (min-width: 768px)
// {
//    .linebreak1
//    {
//       display: block;
//    }
// }
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<br class="linebreak1"/>
<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>


没有必要把自己局限于W3Schools所说的:

enter image description here

另一个不需要添加任何额外标记的解决方案是添加一些动态边距来分隔元素。

在本例中,这可以在calc()的帮助下完成,只需将margin-leftmargin-right添加到3n+2元素(2,5,8)。

.item:nth-child(3n+2) {
background: silver;
margin: 10px calc(50% - 175px);
}

片段的例子

.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+2) {
background: silver;
margin: 10px calc(50% - 175px);
}
<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>

我只是想把这个答案放在一起,意在提醒大家,在适当的条件下,你有时不需要过度思考手头的问题。你想要的东西可以用flex: wrapmax-width而不是:nth-child来实现。

ul {
display: flex;
flex-wrap: wrap;
justify-content: center;
max-width: 420px;
list-style-type: none;
background-color: tomato;
margin: 0 auto;
padding: 0;
}


li {
display: inline-block;
background-color: #ccc;
border: 1px solid #333;
width: 23px;
height: 23px;
text-align: center;
font-size: 1rem;
line-height: 1.5;
margin: 0.2rem;
flex-shrink: 0;
}
<div class="root">
<ul>
<li>A</li>
<li>B</li>
<li>C</li>
<li>D</li>
<li>E</li>
<li>F</li>
<li>G</li>
<li>H</li>
<li>I</li>
<li>J</li>
<li>K</li>
<li>L</li>
<li>M</li>
<li>N</li>
<li>O</li>
<li>P</li>
<li>Q</li>
<li>R</li>
<li>S</li>
<li>T</li>
<li>U</li>
<li>V</li>
<li>W</li>
<li>X</li>
<li>Y</li>
<li>Z</li>
</ul>
</div>

https://jsfiddle.net/age3qp4d/