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:after
的flex-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
而不是flex
和grid template columns
使用repeat
和auto 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:将最后一行与网格对齐的主要内容,如果未能解决你的问题,请参考以下文章