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

时间:2015-04-19 16:29:12

标签: html css css3 flexbox

有没有办法在多行flexbox中换行?

例如,在this CodePen中的每个第3项之后中断。

.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; */    
}

10 个答案:

答案 0 :(得分:260)

最简单,最可靠的解决方案是在正确的位置插入弹性物品。如果它们足够宽(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次换行。

要解决此问题,您可以在flex项目内而不是在flex容器中生成伪元素。这样你就不会局限于2.但是那些伪元素不会是弹性项目,因此它们将无法强制换行。

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

  

元素本身不生成任何框,但它的子元素和   伪元素仍然正常生成框。出于...的目的   框生成和布局,必须将元素视为具有   已被文档中的子元素和伪元素替换   树。

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

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

或者,根据Fragmenting Flex LayoutCSS Fragmentation,Flexbox允许使用break-beforebreak-after或其CSS 2.1别名强制中断:

.item:nth-child(3n) {
  page-break-after: always; /* CSS 2.1 syntax */
  break-after: always; /* New 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;
  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>

flexbox中的强制换行尚未得到广泛支持,但它适用于Firefox。

答案 1 :(得分:20)

@Oriol有一个很好的答案,遗憾的是截至2017年10月,display:contentspage-break-after都没有得到广泛支持,更好地说是关于支持这个但不支持其他玩家的Firefox,我来了以下“hack”我认为比每个第3个元素之后的休息中的硬编码更好,因为这将使页面移动友好变得非常困难。

正如所说它是一个黑客而且缺点是你需要添加相当多的额外元素,但是即使在过时的IE11上也可以实现跨浏览器。

“hack”只是在每个div之后添加一个额外的元素,设置为display:none,然后使用css nth-child来确定哪一个应该实际可见,强制a线刹这样:

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

答案 2 :(得分:16)

从我的角度来看,在flex项之间使用<hr> elements as line breaks更具语义性。

<div class="container">
  <div>1</div>
  <div>2</div>
  <hr>
  <div>3</div>
  <div>2</div>
  ...
</div>

CSS正在关注

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

.container hr {
  width: 100%;
}

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

答案 3 :(得分:7)

您要语义换行吗?

然后考虑使用<br>。 W3Schools可能会建议您BR仅用于写诗(我的即将出版),但是您可以更改样式,使其表现为100%宽的块元素,将您的内容推到下一行。如果'br'建议一个中断,那么对我来说,比使用hr或100%div更合适,并使html更具可读性。

在需要换行的地方插入<br>并设置其样式。

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

您可以disable <br> with media queries,方法是将display:设置为blocknone(我已经提供了一个示例,但未对此进行注释)。

如果需要,您也可以使用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

答案 4 :(得分:5)

我认为传统方式灵活且易于理解:

<强>标记

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

创建 grid.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;
  }
}

我创建了example (jsfiddle)

尝试在400px下调整窗口大小,它的响应能力很强!!

答案 5 :(得分:1)

我只想把这个答案混在一起,以提醒您-在适当的条件下-有时您不需要考虑当前的问题。可以用flex: wrapmax-width而不是:nth-child来实现。

https://jsfiddle.net/age3qp4d/

答案 6 :(得分:0)

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

在示例中,这可以借助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>

答案 7 :(得分:-1)

对于将来的问题,也可以使用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>

答案 8 :(得分:-2)

我在这里尝试了几个答案,但没有一个起作用。具有讽刺意味的是,所做的工作是可以尝试的<br/>的最简单替代方案:

<div style="flex-basis: 100%;"></div>

或者您也可以这样做:

<div style="width: 100%;"></div>

将其放置在您想要换行的任何地方。似乎甚至可以与相邻的<span>一起使用,但是我正在与相邻的<div>一起使用。

答案 9 :(得分:-3)

&#13;
&#13;
.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;
}
&#13;
<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>
&#13;
&#13;
&#13;

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