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


236

有没有办法在多行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; */    
}

1
我有相同或非常相似的问题;我想破坏每第4个项目,所以我只是将每个flex项目的宽度设置为25vw(或25%)。因此,对于您的情况,每第三个项目,您将使用33.3vw(或33.3%)。为我想要的完美工作。如果其他人正在寻找更简单的方法,可能会有所帮助。
本·克拉克

本·克拉克!非常感谢!您的答案是唯一可行的答案。您可以考虑将其添加为答案。:-)
itmuckel

Answers:


322

最简单,最可靠的解决方案是在适当的位置插入弹性项目。如果它们足够宽(width: 100%),则会强制换行。

但这是丑陋的,不是语义上的。取而代之的是,我们可以在flex容器内生成伪元素,并将order其移动到正确的位置。

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

为了解决这个问题,您可以在flex项目内部而不是在flex容器中生成伪元素。这样,您将不会被限制为2。但是这些伪元素不会是flex项目,因此它们将无法强制换行。

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

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

因此,您可以将其应用于display: contentsflex容器的子容器,并将每个容器的内容包装在其他包装器中。然后,弹性项目将是那些额外的包装和子项的伪元素。

另外,根据碎片的Flex布局CSS碎片,Flexbox,就允许通过使用强制休息break-beforebreak-after或它们的CSS 2.1别名:

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

尚不广泛支持flexbox中的强制换行符,但可在Firefox上使用。


@Oriol关于第一种方法,为什么您说它很丑而不是语义?只是好奇。
nacho4d

18
@ nacho4d因为不应出于样式目的而修改HTML。而且,如果您改变主意并决定使用4列而不是3列,则可能需要修改很多HTML。与break-after解决方案进行比较,该解决方案仅需要修改样式表中的选择器。
Oriol

1
我需要添加display: block;.container ::before::after伪类,可以在IE浏览器的解决方案数量的两项工作。YMMV!
缠绕

1
@twined这很奇怪,因为弹性项目应该自动被阻止。
Oriol

2
由于分页符显然已从规范中删除,是否有可能使您的第二个片段在列方向上运行而又不扩大其容器的高度?我没有运气,将flex-basis设置为100%/项目会延长它的高度。
Lucent

42

在我看来,将<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中进行了测试。


7
我也是这样做的,效果很好。加hr {flex-basis:100%; 高度:0;边距:0; 边界:0; }使中断变得无缝。
Besworks

我喜欢这种方法。注意:使用gap: 10px;行之间的距离实际上是20px。要解决此问题,请指定行间距的一半:gap: 5px 10px;
CuddleBunny

@Besworks:border应设置为none,而不是0
标记

@mark border:0;与一样有效border:none;。参见:stackoverflow.com/questions/2922909/…–
Besworks

23

@Oriol有一个很好的答案,可悲的是,截至2017年10月,这两个都没有display:contents,也没有page-break-after得到广泛支持,最好说的是Firefox支持此功能,但其他播放器则不支持,我想出了以下“ hack”,我认为这比硬要好在每个第3个元素之后进行一次编码,因为这将使页面移动友好性变得非常困难。

就像说的那样,这是一个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>


2
我还发现“ display:contents”和“ page-break-after”方法不起作用,因此采用了这种“ hack”。据报道,这是一个Chrome错误,并标记为“ WontFix”(请参见bugs.chromium.org/p/chromium/issues/detail?id=473481),其解释为:“根据CSS工作组的说法,没有当前使用CSS在Flex框中强制换行的方法。”
Martin_W

您可以使用选择器来避免混乱.container>p。然后,所有这些<p></p>标签都不需要该class属性。不是重要的,当然。只是我懒惰的大脑为您的智能解决方案找到了一个微小的,节省空间的调整。当然,它也依赖没有其他<p>标签的用户作为.containerdiv的直接子级。从技术上讲,你可以做其他所有相同<div>的孩子,但你有很多更可能有其他<div>在S .container比你<p>S,所以可能不是一个明智的举动在那里。
史蒂夫

13

您要语义换行吗?

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

<br>在需要换行的位置插入并对其进行样式设置。

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

您可以通过设置为或适当地禁用<br>媒体查询,(我已经提供了一个示例,但已将其注释掉了)。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所说的话:

在此处输入图片说明


技术的一种扩展是<br class="2col">在第二个项目<br class="3col">之后,第三个项目之后放置。然后将一个类cols-2应用于容器并创建CSS,以仅为该列数启用适当的换行符。例如。br { display: none; } .cols-2 br.2col { display: block; }
Simon_Weaver


2
我将更改措辞,以免将其呈现为完美的解决方案,但在某些情况下,我认为这并不比其他div或伪元素解决方案差。也许我现在就去写一首诗。
Simon_Weaver

是的...一首诗会很好,别忘了在此处发布链接:) ...关于一个完美的解决方案,break-*尽管不幸的是,它还没有跨浏览器,但是有一个(在接受的答案中显示) ,因此,第二好的选择是使用一个元素,该元素本身会填充其父元素的宽度,然后将任何下一个同胞推入自己的行中,这同样在接受的答案中给出。因此,从语义上来说,使用除块之外的其他任何元素在语义上都将更糟,例如br
阿森(Ason)

5
记住,您发布的是W3School而不是W3C的打印,因为它们没有连接。
Edu Ruiz

7

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

标记

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

我创建了一个示例(jsfiddle)

尝试将窗口调整为400px以下的大小,它具有响应性!!


在这种解决方案中,元素是在一起的,其想法是在元素之间留一个长的空白。
Juanma Menendez

2

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

在示例的情况下,可以借助calc(),只需将3n + 2元素(2,5,8)添加margin-leftmargin-right即可完成此操作

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


1
这值得一票。使用flex和margin的组合是支持换行的一种非常简单的方法。calc如此答案中所述,它也非常有效。
stwilz

我更喜欢这个,只是margin-right: 1px项目,它将使下一个项目从新行开始。
arvil

0

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


3
这里的问题是OP指出解决方案必须使用flexbox display: flex;,而不是display: inline-block;
bafromca

1
你可以为写.cell:nth-child(3n + 1)而不是
Si7ius

-1

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

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

或者您也可以这样做:

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

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


2
100%宽度的div是公认的答案中给出的第一个解决方案。
TylerH

1
是的,有点。他们因为一个不好的原因而被鄙视(丑陋,真的吗?)。另外,我的答案有flex-basis
安德鲁(Andrew)

-4

.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,只要拥有一个好的结构就可以解决问题。


1
您可以将容器display: block设为普通容器,然后将这些新的第2层divs弹性盒。这适用于行。使用列模式时,将div替换为spans。
jiggunjer
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.