Flex-box:将最后一行与网格对齐

Posted

技术标签:

【中文标题】Flex-box:将最后一行与网格对齐【英文标题】:Flex-box: Align last row to grid 【发布时间】:2013-09-15 15:40:44 【问题描述】:

我有一个简单的 flex-box 布局,其中包含如下容器:

.grid 
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;

现在我希望最后一行中的项目与其他项目对齐。应该使用justify-content: space-between;,因为可以调整网格的宽度和高度。

目前看起来像

在这里,我希望右下角的项目位于“中间列”中。实现这一目标的最简单方法是什么?这是一个小的jsfiddle,它显示了这种行为。

.exposegrid 
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;


.exposetab 
  width: 100px;
  height: 66px;
  background-color: rgba(255, 255, 255, 0.2);
  border: 1px solid rgba(0, 0, 0, 0.4);
  border-radius: 5px;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
  margin-bottom: 10px;
<div class="exposegrid">
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
  <div class="exposetab"></div>
</div>

【问题讨论】:

复制:***.com/questions/16377972/… 在此处查看我的解决方案,我认为无需 hack 就可以很好地工作,只是数学:***.com/questions/18744164/… 或者,可以使用较新的css grid module - 没有这个问题 Targeting flex items on the last row 我为子宽度可变的情况添加了一个通用的 JS 解决方案,使行上的项目数也可变。 【参考方案1】:

添加自动填充空间的::after。无需污染您的 html。这是一个显示它的代码笔:http://codepen.io/DanAndreasson/pen/ZQXLXj

.grid 
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;


.grid::after 
  content: "";
  flex: auto;

【讨论】:

有没有可能让它以某种方式在空间周围工作? @DanAndreasson 有两个问题,它不是从左边开始的(比如 space-between),而且最后一行的项目之间的空间与上一行不同(模拟一些固定的“任意大小”网格中的宽度项目 - 与两者有关)...codepen.io/anon/pen/gPoYZE 我想要的是保持“策略”(空间或空间之间),但从左侧开始,就像前几行一样。 . 我想知道,是否可以概括您的惊人解决方案。 这仅适用于项目有填充来分隔它们,并且每组 4 个的组合百分比宽度等于 100%。In this codepen 我从 .grid 中删除了 justify-content: space-between; 并删除了 .grid:after它的工作原理相同。现在,如果您尝试了like this,它就会完全崩溃。请注意,每组 4 个的宽度加起来不等于 100%。在OP's fiddle 中,宽度以像素为单位设置,因此您的解决方案doesn't work 这种情况。 尝试此解决方案时,最初,最后一行缺少的项目没有与space-between 正确分布。但是,当我将.grid:afterflex-basis 设置为与网格中其他项目相同的大小(每个断点,覆盖上述默认/基本模块代码)时,最后一行正确展开。似乎可以在 Safari、ios、Firefox、Chrome(需要测试 IE)上运行,并且在我的初始实现中,我的最大行大小是 3。 根据我的需要,这适用于以下修改: content: "";flex: 0 0 32%;max-width: 480px;,我通过媒体查询更改更改了最大宽度,因此网格在所有宽度上都是完美的。【参考方案2】:

一种技术是插入一些高度为零的额外元素(与您期望的连续元素的最大数量一样多)。空间仍然被分割,但多余的行折叠成空:

http://codepen.io/dalgard/pen/Dbnus

body 
  padding: 5%;


div 
  overflow: hidden;
  background-color: yellow;


ul 
  display: flex;
  flex-wrap: wrap;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;


li 
  flex: 1 0 200px;
  height: 200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;

li:empty 
  height: 0;
  border: none;


*,
:before,
:after 
  box-sizing: border-box;
<div>
  <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></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

未来,这可能会通过使用多个::after(n) 来实现。

【讨论】:

不幸的是,这以非语义方式污染了标记,但它完全有效。 :S 我希望我知道任何其他不需要非语义元素的方式来复制这种行为,flexbox 或其他方式。 同意,它很脏,但它可以工作,并且比很多黑客都少hacky。去死吧,我一直在使用它,直到 ::after(12) 获得支持,或者他们添加了一些额外的 justify 选项。真的很遗憾,因为 flexbox justify 目前的工作方式是完全错误的!如果您要证明一段文本的合理性,那么您永远不会尝试证明最后一行的合理性。绝对应该是一个选择,我不敢相信他们错过了这个。 我想出了一个纯 CSS 的解决方案.. 需要注意的是它只能解决两个丢失的项目,因此只能在每个包装行最多三个项目的弹性网格中安全地工作。 Demo:codepen.io/lukejacksonn/pen/dozqVq这里的原理是使用伪元素作为extra children,并赋予它们与容器中的item相同的flex属性。 @Codemonkey 耶稣。我才开始使用 flexbox,想着如何摆脱所有这些旨在将这些内联块对齐网格内的黑客,现在事实证明这根本不可能!我马上就达到了那个障碍,达到了我认为我很难愉快地解决所有这些旧的无法解决的 CSS 问题的极限。没那么快,我猜。只用了 20 年就得到了正确的垂直定心——我们当然可以等待。天啊,这任务似乎太简单了…… @dalgard 我不这么认为。见my comment。【参考方案3】:

正如其他海报所提到的 - 没有干净的方法将最后一行与 flexbox 左对齐(至少按照当前规范)

然而,不管它的价值:使用CSS Grid Layout Module,这非常容易产生:

基本上相关代码归结为:

ul 
  display: grid; /* 1 */
  grid-template-columns: repeat(auto-fill, 100px); /* 2 */
  grid-gap: 1rem; /* 3 */
  justify-content: space-between; /* 4 */

1) 使容器元素成为网格容器

2) 使用宽度为 100 像素的自动列设置网格。 (注意auto-fill 的使用(与auto-fit 相对) - (对于 1 行布局)将空轨道折叠为 0 - 导致项目扩展以占用剩余空间。这将导致合理的 ' space-between' 布局,当网格只有一行时,这在我们的例子中不是我们想要的。(查看this demo 以了解它们之间的区别)。

3) 为网格行和列设置间隙/间距 - 在这里,因为需要“间距”布局 - 间隙实际上是最小间隙,因为它会根据需要增大。

4) 类似于 flexbox。

ul 
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
  grid-gap: 1rem;
  justify-content: space-between;
  
  /* boring properties */
  list-style: none;
  background: wheat;
  padding: 2rem;
  width: 80vw;
  margin: 0 auto;


li 
  height: 50px;
  border: 1px solid green;
<ul>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

Codepen Demo(调整大小看效果)

【讨论】:

不错的解决方案。唯一的问题是它不适用于 IE10/11。 鉴于当前的可能性,这现在应该是公认的答案。使用:after 伪元素可能会在极端情况下导致不需要的结果。 @Danield 这个建议对我帮助很大,谢谢! 这应该是公认的答案。本着渐进增强的精神,我会将它与 flexbox 结合起来作为后备:不支持网格的浏览器将显示 flexbox 版本,这对我来说足够接近。 非常感谢,你拯救了我这一周我一直在寻找这个的一天【参考方案4】:

没有任何额外的标记,只需添加 ::after 就可以为我指定列的宽度。

.grid 
  display:flex;
  justify-content:space-between;
  flex-wrap:wrap;

.grid::after
  content: '';
  width: 10em // Same width of .grid__element

.grid__element
  width:10em;

使用这样的 HTML:

<div class=grid">
   <div class="grid__element"></div>
   <div class="grid__element"></div>
   <div class="grid__element"></div>
</div>

【讨论】:

这很有趣,但并不完全正确。当您处理底行中的两个以上元素时,问题就出现了——上行元素之间出现的间距永远不会出现在最后一行;这些物品被硬包装在一起,否定了空间之间的原始实用性。 如果你使用flex-basis: 10em而不是宽度会更好。【参考方案5】:

我知道这里有很多答案,但是.. 最简单的方法是使用grid 而不是flexgrid template columns 使用repeatauto fills,您必须在其中设置数字您为每个元素提供的像素数,100px 来自您的 sn-p 代码。

.exposegrid 
     display: grid;
     grid-template-columns: repeat(auto-fill, 100px);
     justify-content: space-between;

 .exposetab 
     width: 100px;
     height: 66px;
     background-color: rgba(255, 255, 255, 0.2);
     border: 1px solid rgba(0, 0, 0, 0.4);
     border-radius: 5px;
     box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.2);
     margin-bottom: 10px;
<div class="exposegrid">
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
   <div class="exposetab"></div>
</div>

【讨论】:

这是使最后一行项目左对齐的正确解决方案。 我同意,正确的方法是使用网格。它可以通过 flexbox 实现,但使用网格更简洁。【参考方案6】:

你不能。 Flexbox 不是网格系统。它没有语言结构来满足您的要求,至少在您使用justify-content: space-between 时不会。与 Flexbox 最接近的是使用列方向,这需要设置显式高度:

http://cssdeck.com/labs/pvsn6t4z(注意:不包括前缀)

ul 
  display: flex;
  flex-flow: column wrap;
  align-content: space-between;
  height: 4em;

但是,只使用列会更简单,它具有更好的支持并且不需要设置特定的高度:

http://cssdeck.com/labs/dwq3x6vr(注意:不包括前缀)

ul 
  columns: 15em;

【讨论】:

有办法;看我的回答。 @dalgard,您的回答是一种解决方法,而不是真正的解决方案。 cimanon 的答案是正确的。 @Jonah 我认为“技术”是对我的回答的公平描述。它确实为很多人提供了解决方案,包括提问者。 @dalgard 这并没有改变 Flexbox 不提供语言结构来完成所要求的事情这一事实。此外,我认为添加虚假元素是一种非常肮脏的做法,就像使用表格进行布局一样。 它并不漂亮,但前端开发是可能的艺术;实用主义是一个基本前提。我认为 extremely 这个词用错了,因为在 99.9% 的真实世界网站(参见 Bootstrap 容器元素)上都使用了额外的元素来进行样式设置。【参考方案7】:

一种可能的解决方案是在.grid 容器上使用justify-content: flex-start;,对其子元素的大小进行限制,并在适当的子元素上使用边距——具体取决于所需的列数。

对于 3 列网格,基本 CSS 如下所示:

.grid 
    display: flex;
    flex-flow: row wrap;
    justify-content: flex-start;


.grid > * 
    flex: 0 0 32%;
    margin: 1% 0;


.grid > :nth-child(3n-1) 
    margin-left: 2%;
    margin-right: 2%;

这是另一个不完美的解决方案,但它确实有效。

http://codepen.io/tuxsudo/pen/VYERQJ

【讨论】:

【参考方案8】:

如果您想要一个在项目之间有一些空间的网格,并且项目开始时没有任何初始空间,那么这个简单的解决方案可以工作:

.grid 
    display: flex;
    flex-flow: row wrap;
    margin: 0 -5px; // remove the inital 5px space
    width: auto;

.grid__item 
    width: 25%;
    padding: 0 5px; // should be same as the negative margin above.

如果你想要最初的 5px 空间,那么只需删除负边距 :) 简单。

https://jsfiddle.net/b97ewrno/2/

公认的答案虽然不错,但它会导致第二行的元素之间没有空格..

【讨论】:

很惊讶这没有更多的赞成票。这是属于 Flex 博物馆的绝妙方法。 @EduardoLaHozMiranda 谢谢!但为什么是“博物馆”? IE11 不支持 CSS 网格,大多数网站仍然需要支持。 + 前端开发中的一些大人物仍然声称网格与网格有不同的用例。弹性盒。但也许你的意思是这应该是网络历史的重要组成部分:D 大声笑,是的。我当时很兴奋。只是意味着这是对这个问题的一个伟大而最小的看法。 @dencey 你不需要知道对于这个解决方案,它是 25%,所以每行最多 4 个,但你可以使用任何你想要的百分比 @OZZIE 固定项目宽度,而不是百分比,指问题中的样式,期望的效果是项目与两侧的容器边缘对齐,并且每行项目之间的空间相等。 jsfiddle.net/n6k831Ld【参考方案9】:

是的。!我们可以通过一些媒体查询和预定义的最大列数

这里使用 4 列。检查我的代码:

.container 
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  flex-flow: row wrap;
  -webkit-flex-flow: row wrap;
  -moz-flex-flow: row wrap;


.container .item 
  display: flex;
  display: -webkit-flex;
  display: -moz-flex;
  justify-content: center;
  -webkit-justify-content: center;
  -moz-justify-content: center;
  flex-basis: 25%; //max no of columns in %, 25% = 4 Columns


.container .item .item-child 
  width: 130px;
  height: 180px;
  background: red;
  margin: 10px;


@media (max-width: 360px) 
  .container .item 
    flex-basis: 100%;
  


@media (min-width:360px) and (max-width: 520px) 
  .container .item 
    flex-basis: 50%;
  


@media (min-width:520px) and (max-width: 680px) 
  .container .item 
    flex-basis: 33.33%;
  
<div class="container">

  <div class="item">
    <div class="item-child">1</div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>
  <div class="item">
    <div class="item-child"></div>
  </div>

</div>

注意 1)无需创建子div。它可以是任何其他标签,如 'img' r 无论你想要什么.. 2)如果您想要更多列,请调整媒体查询和最大列数。

【讨论】:

这只会在最新的 IE 中创建 3 个【参考方案10】:

使用 CSS 网格为我解决了这个问题,

此解决方案仅适用于您拥有固定数量的列,即否。在一行中显示的元素数

-> 使用网格但不指定行数,随着元素数量的增加,它会换行并动态添加行,我在此示例中指定了三列

->您不必为您的孩子/单元格提供任何位置,因为它会修复它,这是我们不想要的。

.grid-class
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  column-gap: 80px;

【讨论】:

这对我来说是最好的解决方案!【参考方案11】:

如果要将最后一项与网格对齐,请使用以下代码:

网格容器

.card-grid 
  box-sizing: border-box;
  max-height: 100%;
  display: flex;
  flex-direction: row;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  justify-content: space-between;
  align-items: stretch;
  align-content: stretch;
  -webkit-box-align: stretch;
  -webkit-box-orient: horizontal;
  -webkit-box-direction: normal;
  -ms-flex-flow: row wrap;
  flex-flow: row wrap;


.card-grid:after 
  content: "";
  flex: 1 1 100%;
  max-width: 32%;

网格中的项目

.card 
  flex: 1 1 100%;
  box-sizing: border-box;
  -webkit-box-flex: 1;
  max-width: 32%;
  display: block;
  position: relative;


诀窍是将项目的最大宽度设置为等于 .card-grid:after 的最大宽度。

Live demo on Codepen

【讨论】:

cthulu 祝福你和你的电脑 当卡片大小固定且每行卡片数量未知时,此方法不起作用。 codepen.io/zendu/pen/WXNGvo【参考方案12】:

你也可以这样做:

.exposegrid:last-child 
  margin-right: auto;

【讨论】:

【参考方案13】:

可以使用“flex-start”并手动添加边距。它需要一些数学技巧,但绝对很容易做到,并且可以很容易地与像 LESS 这样的 CSS 预处理器一起使用。

例如看这个LESS mixin:

.flexboxGridMixin(@columnNumber,@spacingPercent) 
  @contentPercent: 100% - @spacingPercent;
  @sideMargin: @spacingPercent/(@columnNumber*2);
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  > * 
    box-sizing: border-box;
    width: @contentPercent/@columnNumber;
    margin-left: @sideMargin;
    margin-right: @sideMargin;
  

然后它可以很容易地用于显示响应式网格布局:

ul 
  list-style: none;
  padding: 0;
  @spacing: 10%;
  @media only screen and (max-width: 499px)  .flexboxGridMixin(1,@spacing); 
  @media only screen and (min-width: 500px)  .flexboxGridMixin(2,@spacing); 
  @media only screen and (min-width: 700px)  .flexboxGridMixin(3,@spacing); 
  @media only screen and (min-width: 900px)  .flexboxGridMixin(4,@spacing); 
  @media only screen and (min-width: 1100px)  .flexboxGridMixin(5,@spacing); 


li 
  background: pink;
  height: 100px;
  margin-top: 20px;

这是一个例子

http://codepen.io/anon/pen/YyLqVB?editors=110

【讨论】:

你从不使用@contentPercent。你打算这样做吗? 宽度:@contentPercent/@columnNumber; 哇!这个解决方案给我留下了深刻的印象。我会尽量适应我的情况【参考方案14】:

这是很多答案的组合,但它完全符合我的需要——也就是说,将 flex 容器中的最后一个子元素向左对齐,同时保持间隔行为(在这种情况下,它是三列布局)。

这是标记:

.flex-container 
  display: flex;
  justify-content: space-between;
  flex-direction: row;


.flex-container:after 
  content: "";
  flex-basis: 30%;

【讨论】:

更通用:flex-basis size 必须等于 child 的 size。 我发现 flex-grow: 0.9 而不是 flex-basis 适用于任意数量的列。在一堆现代浏览器中测试 - 它适用于所有浏览器,但填充在 IE 中被破坏(但在 Edge0 中工作【参考方案15】:

如果您希望网格视图中的项目与最后一个元素的距离相等。确保您的卡片宽度为 100% 使用以下 CSS。这很好用

.container 
  /* ... snip ... */
  display: grid;
  grid-template-columns: repeat(auto-fill, 100px);
  justify-content: space-between;
  grid-gap: 20px;

【讨论】:

【参考方案16】:

这个版本最适合固定宽度的块:

http://codepen.io/7iomka/pen/oxxeNE

在其他情况下 - dalgard 的版本

http://codepen.io/dalgard/pen/Dbnus

body 
  padding: 5%;


div 
  overflow: hidden;
  background-color: yellow;


ul 
  display: flex;
  flex-wrap: wrap;
justify-content:center;
  margin: 0 -4px -4px 0;
  list-style: none;
  padding: 0;


li 
  flex: 1 0 200px;
  height: 200px;
  max-width:200px;
  min-width:200px;
  border-right: 4px solid black;
  border-bottom: 4px solid black;
  background-color: deeppink;

li:empty 
  height: 0;
  border: none;


*,
:before,
:after 
  box-sizing: border-box;
<div>
  <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></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
  </ul>
</div>

【讨论】:

【参考方案17】:

只需添加几个具有相同属性的假项目,除了高度设置为 0px 到最后。

【讨论】:

添加假货在各个方面都是不好的做法。除非是强制性的,否则您不应该仅仅为了破解 css 而在 DOM 中填充东西。出于许多原因,从可访问性,到用奇怪的东西充斥代码库,再到使逻辑更复杂,难以理解,并且继续列出。除非您明确表示这可能是一个糟糕的解决方案或有特殊情况,否则不要推荐 hack。 @Eksapsy 好吧,我找不到任何解决方案在 100% 的情况下工作且不使用 javascript。使用 javascript 会使事情变得更加复杂。网格+列模板?也许它也必须在 IE11 中工作,所以不。 nth-child、last-child、'after' 说明符......这些都不适用于特定场景。有时除了使用丑陋的代码或较低的设计要求之外别无他法。 有趣的是,这实际上是唯一可行的解​​决方案(除了 JS-hacking),它有 0 票。嗯……不再了!无论如何,您需要添加的空 div 的数量是 N - 1,其中 N 是一行中的最大项目数。请注意,此解决方案允许容器将 space-around、space-between 和 space-evenly 用于其 justify-content 属性。最好将空 div 设置为 flex: 0 0 nn 其中 nn 与真实元素具有相同的 flex-basis。【参考方案18】:

即使 Flexbox 出现了差距,我也会添加一个可行的解决方案。

它使用兄弟组合器来检查 2 个条件。

它检查的第一个条件是元素是否是倒数第二个div:nth-last-child(2)

对于 4 列布局,我们需要检查位置 2 和 3 检查它是否在 4 的第二行 div:nth-of-type(4n+2) 或第三行 div:nth-of-type(4n+3)

对于 3 列布局,我们只需要检查位置 2

div:nth-of-type(3n+2)

然后我们可以像下面这样组合 4 列布局

div:nth-last-child(2) + div:nth-of-type(4n+2)

div:nth-last-child(2) + div:nth-of-type(4n+3)

我们还需要处理一个边缘情况,任何 3n+2 和 4 的倍数的数都将获得 35% 的边距右div:nth-last-child(2) + div:nth-of-type(4n+4)

3 列布局将是

div:nth-last-child(2) + div:nth-of-type(3n+2)

然后我们需要给上面的选择器添加一个边距。需要计算 margin-right 并且取决于 flex-basis。

我添加了一个包含 3 列和 4 列的示例以及一个媒体查询。我还添加了一个小的 JavaScript 按钮,用于添加一个新的 div,以便您检查它是否有效。

这是一点点 CSS,但它可以工作。 如果您需要更多解释,我也在我的网站上写过这个。 https://designkojo.com/css-programming-using-css-pseudo-classes-and-combinators

var number = 11;

$("#add").on("click", function() 
    number = number + 1;
    $("#main").append("<div>" + number + "</div>");
);
body 
  margin: 0;

main
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  align-content: flex-start; /* vertical */
  justify-content: space-between;
  min-width: 300px;
  max-width: 1200px;
  margin: 20px auto;
  background-color: lightgrey;
  height: 100vh;

div 
  flex-basis: 30%;
  background-color: #5F3BB3;
  min-height: 20px;
  height: 50px;
  margin-bottom: 20px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #9af3ff;
  font-size: 3em;



div:nth-last-child(2) + div:nth-of-type(3n+2) 
  background-color: #f1b73e;
  margin-right: 35%;


@media screen and (min-width: 720px) 

  div 
    flex-basis: 22%;
  

  div:nth-last-child(2) 
    background-color: greenyellow;
  

  div:nth-of-type(4n+2) 
    background-color: deeppink;
  

  /* Using Plus combinator is for direct sibling */
  div:nth-last-child(2) + div:nth-of-type(4n+2) 
    background-color: #f1b73e;
    margin-right: 52%;
  

  div:nth-last-child(2) + div:nth-of-type(4n+3) 
    background-color: #f1b73e;
    margin-right: 26%;
  

  /* Also need to set the last to 0% to override when it become (3n+2)
   * Any number that is 3n+2 & multiple of 4 will get the 35% margin-right
   * div:nth-last-child(2) + div:nth-of-type(3n+2)
   */

  div:nth-last-child(2) + div:nth-of-type(4n+4) 
    background-color: #f1b73e;
    margin-right: 0;
  

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css">
  <title>My New Project</title>
</head>

<body>

<header>


</header>

<button id="add">Add</button>
<main id="main">

  <div>1</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>


</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="action.js"></script>
</body>
</html>

【讨论】:

【参考方案19】:

虽然您需要满足以下条件,但有一种方法可以不使用 flexbox。 1)容器有填充物。 2) 项目大小相同,您确切知道每行需要多少个。

ul 
  padding: 0 3% 0 5%;

li 
  display: inline-block; 
  padding: 0 2% 2% 0;
  width: 28.66%;

容器右侧较小的填充允许每个列表项右侧的额外填充。假设与列表对象相同的父项中的其他项用 0 5% 填充,它将与它们齐平。您还可以将百分比调整为您想要的边距或使用计算 px 值。

当然,您可以通过使用 nth-child (IE 9+) 删除容器上的边距来执行相同的操作,而无需容器上的填充。

【讨论】:

【参考方案20】:

使用 flexbox 和一些媒体查询,我做了一个小变通方法:http://codepen.io/una/pen/yNEGjv(它有点 hacky 但有效):

.container 
  display: flex;
  flex-flow: row wrap;
  justify-content: flex-start;
  max-width: 1200px;
  margin: 0 auto;


.item 
  background-color: gray;
  height: 300px;
  flex: 0 30%;
  margin: 10px;

  @media (max-width: 700px) 
     flex: 0 45%;
  

  @media (max-width: 420px) 
    flex: 0 100%;
  

  &:nth-child(3n-1) 
    margin-left: 10px;
    margin-right: 10px;
  

【讨论】:

【参考方案21】:

我为它做了一个 SCSS mixin。

@mixin last-row-flexbox($num-columns, $width-items)

  $filled-space: $width-items * $num-columns;
  $margin: calc((100% - #$filled-space) / (#$num-columns - 1));

  $num-cols-1 : $num-columns - 1;

  &:nth-child(#$num-columnsn+1):nth-last-child(-n+#$num-cols-1) ~ & 
    margin-left: $margin;
  
  @for $i from 1 through $num-columns - 2  
    $index: $num-columns - $i;
    &:nth-child(#$num-columnsn+#$index):last-child
      margin-right: auto;
    
  

这是codepen链接:http://codepen.io/diana_aceves/pen/KVGNZg

您只需以百分比和列数设置项目宽度。

希望对你有帮助。

【讨论】:

【参考方案22】:

这是另外几个 scss mixin。

这些 mixin 假定您不会使用 Isotope 之类的 js 插件(它们不尊重 html 标记顺序,因此会混淆 css nth 规则)。

此外,您将能够充分利用它们,尤其是当您以移动优先方式编写响应式断点时。理想情况下,您将在较小的断点上使用 flexbox_grid() 并在以下断点上使用 flexbox_cell()。 flexbox_cell() 将负责重置以前设置的边距,不再用于较大的断点。

顺便说一句,只要您正确设置了容器的 flex 属性,如果需要,您也可以只对项目使用 flexbox_cell()。

代码如下:

// apply to the container (for ex. <UL> element)
@mixin flexbox_grid($columns, $gutter_width)

  display: flex;
  flex-direction:row;
  flex-wrap:wrap;
  justify-content: flex-start;

  > *
    @include flexbox_cell($columns, $gutter_width);
  


// apply to the cell (for ex. a <LI> element)
@mixin flexbox_cell($columns, $gutter_width)
  $base_width: 100 / $columns;
  $gutters: $columns - 1;
  $gutter_offset: $gutter_width * $gutters / $columns;

  flex-grow: 0;
  flex-shrink: 1;
  flex-basis: auto; // IE10 doesn't support calc() here

  box-sizing:border-box; // so you can freely apply borders/paddings to items
  width: calc( #$base_width% - #$gutter_offset );

  // remove useless margins (for cascading breakponts)
  &:nth-child(#$columnsn)
    margin-right: 0;
  

  // apply margin
  @for $i from 0 through ($gutters)
    @if($i != 0)
      &:nth-child(#$columnsn+#$i)
        margin-right: $gutter_width;
      
    
  

用法:

ul
   // just this:
   @include flexbox_grid(3,20px);


// and maybe in following breakpoints, 
// where the container is already setted up, 
// just change only the cells:

li
   @include flexbox_cell(4,40px);

显然,最终由您来设置容器的填充/边距/宽度和单元格的底部边距等。

希望对你有帮助!

【讨论】:

【参考方案23】:

这很 hacky,但它对我有用。我试图实现一致的间距/边距。

.grid 
  width: 1024px;
  display: flex;
  flex-flow: row wrap;
  padding: 32px;
  background-color: #ddd;  

  &:after 
    content: "";
    flex: auto;
    margin-left:-1%;
  

  .item 
    flex: 1 0 24.25%;
    max-width: 24.25%;
    margin-bottom: 10px;
    text-align: center;
    background-color: #bbb;

    &:nth-child(4n+2),
    &:nth-child(4n+3),
    &:nth-child(4n+4) 
      margin-left: 1%;
    

    &:nth-child(4n+1):nth-last-child(-n+4),
      &:nth-child(4n+1):nth-last-child(-n+4) ~ .item 
        margin-bottom: 0;
        

  

http://codepen.io/rustydev/pen/f7c8920e0beb0ba9a904da7ebd9970ae/

【讨论】:

【参考方案24】:

似乎没有人在最后一项上提出 flex-grow 解决方案。 这个想法是让你的最后一个弹性项目占据它可以使用 flex-grow: 1 的所有位置。

.grid 
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;


.grid > *:last-child 
  flex-grow: 1;

注意:这个解决方案并不完美,特别是如果您的弹性项目中有居中元素,因为它会以可能巨大的最后一个弹性项目为中心。

【讨论】:

【参考方案25】:

天哪,我想我找到了一个用最少的 CSS 和没有 JS 的好解决方案。看看吧:

img width:100%;
li 
  display: inline-block;
  width:8em;
  list-style:none;

ul text-align: justify;
<ul>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li>
    <img src="http://www.planwallpaper.com/static/images/kitty-cat.jpg" />
  </li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
  <li></li>
</ul>

这里的关键是要记住,我们正在努力实现的目标正是 text-align: justify 所做的!

HTML 中的空元素可以在不改变外观的情况下完美显示最后一行,但考虑到您想要实现的目标,可能不需要。为了在每种情况下达到完美平衡,您至少需要 x-4 个空元素,x 是要显示的元素数,或者 n-2,n 是要显示的列数。

【讨论】:

【参考方案26】:

假设:

您想要带环绕的 4 列网格布局 项数不一定是4的倍数

为每个项目设置左边距,除了第 1、5 和 9 个项目等。如果左边距为 10px,则每行将有 30px 的边距分布在 4 个项目中。 item 的百分比宽度计算如下:

100% / 4 - horizontal-border - horizontal-padding - left-margin * (4 - 1) / 4

对于涉及弹性盒最后一行的问题,这是一个不错的解决方法。

.flex 
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 1em 0 3em;
  background-color: peachpuff;


.item 
  margin-left: 10px;
  border: 1px solid;
  padding: 10px;
  width: calc(100% / 4 - 2px - 20px - 10px * (4 - 1) / 4);
  background-color: papayawhip;


.item:nth-child(4n + 1) 
  margin-left: 0;


.item:nth-child(n + 5) 
  margin-top: 10px;
<div class="flex">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
</div>
<div class="flex">
  <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>
<div class="flex">
  <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>

【讨论】:

【参考方案27】:

如果您知道行中元素之间的空格宽度和行中元素的数量,这将起作用:

示例:一行 3 个元素,元素之间的间距为 10px

div:last-child:nth-child(3n+2) 
  flex-grow: 1
  margin-left: 10px

【讨论】:

【参考方案28】:

我修改了 Dan Andreasson 提出的示例,通过在元素上使用右边框来创建人造排水沟。然后,您可以使用 nth-child 删除您需要的列网格计数的最后一个子项上的边框。这是一个演示https://codepen.io/JacobLett/pen/mdVoroM

/* demo only */
body 
margin:0;
padding:0;
max-width:1024px;
margin:0 auto;

.block-list 
background: #ccc;
  border:1px solid #ccc;


.block-list .block-list__item 
background: #eee;

/* demo only */




.block-list .block-list__item 
   min-height: 100px;
   margin-bottom: 1rem;


@media only screen and (min-width: 900px) 
   .block-list 
      display: -webkit-box;
      display: flex;
      flex-wrap: wrap;
      -webkit-box-pack: justify;
      justify-content: space-between;
      background-color: #ffffff;
      margin: 1em auto;
   

   .block-list:after 
      content: "";
      -webkit-box-flex: 1;
      flex: auto;
   

   .block-list__item 
      height: 10em;
      width: 25%;
      box-sizing: border-box;
      border-right: 10px solid white;
   

   .block-list-2 .block-list__item 
      width: 50%;
   

   .block-list-2 .block-list__item:nth-child(2n) 
      border: none;
   

   .block-list-3 .block-list__item 
      width: 33.3%;
   

   .block-list-3 .block-list__item:nth-child(3n) 
      border: none;
   

   .block-list-4 .block-list__item 
      width: 25%;
   

   .block-list-4 .block-list__item:nth-child(4n) 
      border: none;
   
   
   .block-list-5 .block-list__item 
      width: 20%;
   

   .block-list-5 .block-list__item:nth-child(5n) 
      border: none;
   
   
   .block-list-6 .block-list__item 
      width: 16.66%;
   

   .block-list-6 .block-list__item:nth-child(6n) 
      border: none;
   
<h2>2 column</h2>
<div class="block-list block-list-2">
   <div class="block-list__item">1
   </div>
   <div class="block-list__item">2
   </div>
   <div class="block-list__item">3
   </div>
   <div class="block-list__item">4
   </div>
   <div class="block-list__item">5
   </div>
   <div class="block-list__item">6
   </div>
</div>
<h2>3 column</h2>
<div class="block-list block-list-3">
   <div class="block-list__item">1
   </div>
   <div class="block-list__item">2
   </div>
   <div class="block-list__item">3
   </div>
   <div class="block-list__item">4
   </div>
   <div class="block-list__item">5
   </div>
   <div class="block-list__item">6
   </div>
</div>

<h2>4 column</h2>
<div class="block-list block-list-4">
   <div class="block-list__item">1
   </div>
   <div class="block-list__item">2
   </div>
   <div class="block-list__item">3
   </div>
   <div class="block-list__item">4
   </div>
   <div class="block-list__item">5
   </div>
   <div class="block-list__item">6
   </div>
</div>
<h2>5 column</h2>
<div class="block-list block-list-5">
   <div class="block-list__item">1
   </div>
   <div class="block-list__item">2
   </div>
   <div class="block-list__item">3
   </div>
   <div class="block-list__item">4
   </div>
   <div class="block-list__item">5
   </div>
   <div class="block-list__item">6
   </div>
</div>
<h2>6 column</h2>
<div class="block-list block-list-6">
   <div class="block-list__item">1
   </div>
   <div class="block-list__item">2
   </div>
   <div class="block-list__item">3
   </div>
   <div class="block-list__item">4
   </div>
   <div class="block-list__item">5
   </div>
   <div class="block-list__item">6
   </div>
</div>

【讨论】:

【参考方案29】:

如果单个子项具有明确的宽度(例如 32%),您可以通过向父项添加 :after 元素并赋予其相同的明确宽度来解决此问题。

【讨论】:

【参考方案30】:

这里有一些解决方案,人们建议编写精确的布局 css 类、使用伪元素伪造最后一项、使用非 flexbox 方法等。

一个大问题是邻居之间的差距(大小写对齐的按钮换行到多行)。在这种情况下,您不希望项目相互接触,需要有间隙。我只想添加一个尊重差距并适用于任意数量项目的采用性解决方案。虽然它也是基于假最后一个元素的想法,但更普遍。有关详细信息,请参阅 sn-p cmets。

html 
  font-size: 1px;


.container 
  font-size: 16rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;


.item 
  background-color: orange;
  border-radius: 10rem;
  box-sizing: border-box;
  color: white;
  margin-bottom: 10rem;
  padding: 15rem 10rem;
  text-align: center;
<!--
Our setup from design (example) used later in calculations:

container-width: 100%; (can be any)
max-per-row = 4;
total = 6;
desired-hor-gap = 10rem; (equal to vert. gap)

If you go dynamic (drawing html according to the coming data either in a backend template or in a frontend template), you have to calculate and then set exact properties inline.

<i> (or any real html element) is needed to set inline styles to arrange the last row properly.

"2" in <i> calc function - is 6 % 4 since calc doesn't allow for "%" operator. But in real life you will calculate these numbers in JS or some backend template anyway.

   Formulas written in elements' calc functions. Seem to be self-descriptive, but the idea is to set for the last fake item the remainder width + hypothetical gaps.
-->

<div class="container">

<div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
<div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
<div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
<div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
<div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>
<div style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4);" class="item">do stuff</div>

<i style="flex: 0 1 calc((100% - (4 - 1) * 10rem) / 4 * (4 - 2) + ( 4 - 2 - 1) * 10rem);"></i>
</div>

【讨论】:

以上是关于Flex-box:将最后一行与网格对齐的主要内容,如果未能解决你的问题,请参考以下文章

Flex-box:将最后一行与网格对齐

将 flex-box 项目与块中最后一个文本行的基线对齐

游戏网格的垂直对齐文本在 flex-box 中不起作用

Flexbox 网格 - 对齐:围绕空格并对齐最后一个项目

居中网格内容,同时左对齐每一行的内容,具有任意项/列宽度

在颤动的网格视图中将最后一行项目居中