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

新手上路,请多包涵

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

例如,在 此 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; */
}

原文由 Artem Svirskyi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

最简单和最可靠的解决方案是在正确的位置插入弹性项目。如果它们足够宽( 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 个。但是那些伪元素不会是 flex 项目,所以它们不能强制换行。

不过幸运的是, CSS Display L3 引入了 display: contents (目前只有Firefox 37支持):

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

因此,您可以将 display: contents 应用于 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>

或者,根据 规范的旧版本,Flexbox 允许使用 break-beforebreak-after 或它们的旧 CSS 2.1 别名来强制中断:

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

但是这些强制换行符只适用于 Firefox,而且我认为它们不应该根据当前规范工作。新提议的方式(未在任何地方实施)是 wrap-beforewrap-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>

原文由 Oriol 发布,翻译遵循 CC BY-SA 4.0 许可协议

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

 .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 中测试。

原文由 Petr Stepanov 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题