如何在CSS Flexbox中指定一个元素来进行换行?

224

我认为这还不是Flexbox标准的一部分,但是是否有一些技巧可以建议或强制在某个元素之后换行?我想对不同的页面大小做出响应,并在没有额外标记的情况下以不同方式换行列表,这样就不会像在下一行上有孤立的菜单项那样,在菜单中间断开。

以下是起始的HTML:

<ul>
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
    <li>Five</li>
</ul>

以及 CSS:

ul {
    display: flex;
    flex-wrap: wrap;
}
我很乐意提供类似以下内容的东西:
/* inside media query targeting width */
li:nth-child(2n) {
    flex-break: after;
}

查看 jsfiddle 获取更完整的设置: http://jsfiddle.net/theazureshadow/ww8DR/


针对视口尺寸的包装,可以使用媒体查询,针对内容数量(如兄弟节点数)的包装,可以使用数量查询 - Michael Benjamin
5个回答

197
您可以通过在容器上设置此选项来实现此目的:
ul {
    display: flex;
    flex-wrap: wrap;
}

你可以在子元素上设置这个:

li:nth-child(2n) {
    flex-basis: 100%;
}

ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
}

li:nth-child(4n) {
  flex-basis: 100%;
}
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>

这会导致子元素在进行任何其他计算之前占用容器宽度的100%。由于容器设置为在没有足够空间的情况下断行,因此在该子元素之前和之后就会发生断行。因此,您可以使用一个空的

元素来强制在其前后元素之间换行。


5
谢谢!举例来说,如果你想要每行显示4个项目,你只需要这样做: li { flex-basis: 25% } - fabio.sang
19
将基础设置为100%或每行元素的100%并不是一个好的解决方案,因为它需要您在容器上设置高度,否则它将扩展。 - Lucent
1
@Lucent,min-height就足够了,对吧?我在想min-height: 1px可能会减轻很多使用情况的担忧。 - Ynot
4
使用这种解决方案可以拉伸元素,否则该元素将无法占据100%的空间。 - llamerr

83

=========================

这里有一篇文章列出了您的所有选项:https://tobiasahlin.com/blog/flexbox-break-to-new-row/

编辑:现在使用Grid非常容易实现:https://codepen.io/anon/pen/mGONxv?editors=1100

最好的方法可能是在断点处更改flex-basis,而不是在特定项后面进行分行。

=========================

ul {
  flex-flow: row wrap;
  display: flex;
}

li {
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 50%;
}

@media (min-width: 40em;){
li {
  flex-basis: 30%;
}

这里是一个示例:http://cdpn.io/ndCzD

============================================

编辑:您可以在特定元素后进行换行!Heydon Pickering 在 A List Apart 文章中展示了一些 css 魔法:http://alistapart.com/article/quantity-queries-for-css

编辑2:请查看此答案:Line break in multi-line flexbox

@luksak 也提供了一个很好的答案。


这是一个相当不错的想法!我已经将它添加到了jsfiddle中。通过试验,我认为我更喜欢基于非百分比的方法,因为百分比会阻止进一步的重新流动,当你缩小容器时,虽然你可以增加更多具体的断点(当它应该变为33%等)。 - theazureshadow
在Chrome桌面版中运行得非常好。很遗憾,在Android <4.4的Android WebViews中无法正常工作 :( - Guillaume Gendre
最重要的是,在不支持flexbox的情况下有一个备选方案。 - Didier Ghys
29
我不认为 alistapart 的文章解释了如何在特定项目上中断。我能看出它讲述了如何选择该项,但没有说明如何打破换行。 - Ben Davis
真的。这是关于根据标记中存在的元素数量而不是在一行中显示的元素数量来实现不同样式的内容。 - certainlyakey
显示剩余4条评论

36

规范的一部分确实听起来像这样...就在“弹性布局算法”和“主要大小”部分:

否则,从第一个未收集的项目开始,逐个收集连续的项目,直到下一个收集的项目无法适应弹性容器的内部主要大小,或遇到强制换行为止。如果第一个未收集的项目不适合,请将其收集到该行中。无论是CSS2.1 page-break-before / page-break-after [CSS21]还是CSS3 break-before / break-after [CSS3-BREAK]属性指定分段断点时,都会强制进行断点。

来自http://www.w3.org/TR/css-flexbox-1/#main-sizing

除了页面断点应该用于打印之外,它确实听起来像(我从规范的另一部分中了解到,这是一个没有flex-wrap: nowrap的可能多行弹性布局),page-break-after: alwaysbreak-after: always 应该引起断点或换行到下一行。

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

.child {
  flex-grow: 1;
}

.child.break-here {
  page-break-after: always;
  break-after: always;
}

然而,我尝试过这种方法,但它在以下浏览器中并未实现:

  • Safari(最高版本7)
  • Chrome(最高版本43 dev)
  • Opera(最高版本28 dev&12.16)
  • IE(最高版本11)

至少对我来说,以下浏览器实现的效果就是我想要的:

  • Firefox(版本28及以上)

示例请参见http://codepen.io/morewry/pen/JoVmVj

我没有在错误追踪器中找到其他请求,所以我在https://code.google.com/p/chromium/issues/detail?id=473481上报告了它。

但是这个话题被带到了邮件列表中,无论听起来如何,他们显然意味着除了分页之外没有其它的意思。因此,在flex布局中没有办法在特定框之前或之后进行包装,除非将连续的flex布局嵌套在flex子级内部或者调整特定的宽度(例如flex-basis: 100%)。当然,这非常令人恼火,因为使用Firefox实现确认了我的猜想:这个功能非常有用。除了改进垂直对齐之外,缺少此功能还会使flex布局在许多情况下失去效用。不得不添加附加的包装标签和嵌套的flex布局来控制行换行点增加了HTML和CSS的复杂性,并且经常使order无用。同样,强制项目的宽度为100%会降低flex布局的“响应”潜力,或需要大量高度特定的查询或计数选择器(例如其他答案中提到的可能实现所需结果的技术)。至少浮动元素有clear属性可以使用。希望在将来某个时候能添加一些东西。


1
听起来有点不专业。据我理解,page-break-after 用于打印时,而 break-after 则用于“页面、列或区域断点行为”,而不是换行。 - Ajedi32
6
请向规范的作者提出问题;正如我所提到的,这是来自Flexbox官方规范,而不是我提供的“酷技巧”建议。顺便说一句,折行 flex 行不严格意义上属于“内联换行符”,也没说我是这样认为的。短语“换到下一行”只是几种随意表达“它不再与其他框框相邻”的方式之一。 - morewry
该死!这看起来非常有前途 :( - Lyrical
如果我们有break-after: row,那就太完美了。然而,目前我们拥有的最小选项是break-after: region,但它只被大约0%的浏览器支持,而break-after: column则已经太重了。考虑一下当您有弹性盒子和多列的情况。打破列并不等同于打破行。 - Mikko Rantalainen

14

在子元素上设置min-width也会创建一个断点。例如,每3个元素就会发生断点。

flex-grow: 1;
min-width: 33%; 
如果有4个元素,第4个元素将占据100%的宽度。如果有5个元素,第4个和第5个元素将各占据50%的宽度。
请确保父元素具有相应的宽度。
flex-wrap: wrap

虽然这个解决方案可行,但更清晰的方法是使用 flex-basis - Rich

3
唯一看起来有效的方法是在容器上设置 flex-wrap: wrap;,然后使想要换行的子元素填满整个宽度,使用 width: 100%; 即可实现。但是如果您不能将元素拉伸到100%(例如,如果它是一个 <img>),则可以对其应用边距,如 width: 50px; margin-right: calc(100% - 50px)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接