Flexbox: 让所有项目都增长,除了最后一行。

40

我目前拥有这个简单的Flexbox布局:

ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li {
  flex-grow: 1;
  padding: 20px;
  margin: 10px;
  background: #ddd;
}
<ul>
    <li>lorem</li>
    <li>ipsum</li>
    <li>dolor</li>
    <li>sit</li>
    <li>amet</li>
    <li>consectetur</li>
    <li>adipisicing</li>
    <li>elit</li>
    <li>sed</li>
    <li>do</li>
    <li>eiusmod</li>
    <li>tempor</li>
    <li>incididunt</li>
    <li>ut</li>
    <li>labore</li>
    <li>et</li>
    <li>dolore</li>
    <li>magna</li>
    <li>aliqua</li>
</ul>

我希望我的元素可以填满容器宽度(像现在一样),但是最后一行要左对齐。正如您所看到的,最后一行尝试填充空间,这有时会使最后一个元素的宽度不美观。

Flexbox可以实现这个效果吗?我找不到方法。


请在此处查看答案:https://dev59.com/WmQo5IYBdhLWcg3wBLny?noredirect=1&lq=1 - Isaac Gregson
这是我想到的第一个解决方案,但我不太喜欢添加额外的标记。此外,这仅适用于固定宽度的元素,所以在这里不起作用。 - zessx
如果您的项目具有相同的宽度,最好使用CSS网格。对于3列:display:grid;grid-template-columns:33.3% 33.3% 33.3% - totymedli
6个回答

72

您可以添加一个具有巨大flex-grow::after伪元素,以便li元素的flex-grow:1将变得微不足道:

ul::after {
  content: '';
  flex-grow: 1000000000;
}

ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li {
  flex-grow: 1;
  padding: 20px;
  margin: 10px;
  background: #ddd;
}
ul::after {
  content: '';
  flex-grow: 1000000000;
}
<ul>
  <li>lorem</li>
  <li>ipsum</li>
  <li>dolor</li>
  <li>sit</li>
  <li>amet</li>
  <li>consectetur</li>
  <li>adipisicing</li>
  <li>elit</li>
  <li>sed</li>
  <li>do</li>
  <li>eiusmod</li>
  <li>tempor</li>
  <li>incididunt</li>
  <li>ut</li>
  <li>labore</li>
  <li>et</li>
  <li>dolore</li>
  <li>magna</li>
  <li>dolore</li>
  <li>magna</li>
  <li>aliqua</li>
</ul>


给其他人的小提示:这只适用于左对齐的弹性盒子。 - Didii

9
您还可以将高度设置为0的空项附加到容器中,使它们占据额外的空间:http://codepen.io/anon/pen/OyOqrG
(源代码来自我的CodePen:
<div class="container">
  <p></p>
  <p></p>
  <p></p>
  ...
  <p class="empty"></p>
  <p class="empty"></p>
</div>



.container {
  max-width: 490px;
  display: flex;
  flex-flow: row wrap;
  background-color: #00f;
}

.container p {
  min-width: 90px;
  margin: 5px;
  background-color: #f00;
  height: 90px;
  flex-grow: 1;
}

.container p.empty {
  height: 0;
  margin-top: 0;
  margin-bottom: 0;
}

1
太聪明了,这比 flex-grow: 1000000000; 的解决方案适用于更多的响应式情况。在您的网格中添加 n-1 个 <span class="empty"></span>,其中 n 是您的最大列数,例如:在较大的屏幕上我最多有4列,3个 .empty 将适用于每种响应式情况。 - Xavier C.

6
面对相同的问题,我用CSS Grid解决了它。 网格的最后一条规则是左对齐,所有元素具有相同的宽度。
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));

ul {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  list-style: none;
  padding: 0;
}
li {
  padding: 20px;
  background: #ddd;
}
<ul>
    <li>lorem</li>
    <li>ipsum</li>
    <li>dolor</li>
    <li>sit</li>
    <li>amet</li>
    <li>consectetur</li>
    <li>adipisicing</li>
    <li>elit</li>
    <li>sed</li>
    <li>do</li>
    <li>eiusmod</li>
    <li>tempor</li>
    <li>incididunt</li>
    <li>ut</li>
    <li>labore</li>
    <li>et</li>
    <li>dolore</li>
    <li>magna</li>
    <li>aliqua</li>
</ul>


1
那是现在前进的方式。谢谢分享。 - velop
完全解决了我的问题,并让我在此过程中更多地了解了网格,已点赞。 - Nathan G-T
使用 auto-fill 代替 auto-fit 可以确保如果只有一个元素,它不会拉伸整行。这里有一篇文章介绍了两者之间的区别。 - Yonah Karp

1
您可以在li上移除flex-grow: 1,并在ul上添加justify-content: space-between

ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  list-style: none;
  padding: 0;
}
li {
  padding: 20px;
  margin: 10px;
  background: #ddd;
}
<ul>
    <li>lorem</li>
    <li>ipsum</li>
    <li>dolor</li>
    <li>sit</li>
    <li>amet</li>
    <li>consectetur</li>
    <li>adipisicing</li>
    <li>elit</li>
    <li>sed</li>
    <li>do</li>
    <li>eiusmod</li>
    <li>tempor</li>
    <li>incididunt</li>
    <li>ut</li>
    <li>labore</li>
    <li>et</li>
    <li>dolore</li>
    <li>magna</li>
    <li>aliqua</li>
</ul>


2
哦...如果我们有多个元素,最后一行不幸的是没有左对齐。 - zessx
li元素在这种情况下不会增长,因此它们的背景之间将会有间隙。尽管如此,对于某些情况来说这可能是可以接受的。 - David Cook

1

您可以设置伪类::last-child。除了最后一个,所有的<li>都会增长。

CSS

ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li {
  flex-grow: 1;
  padding: 20px;
  margin: 10px;
  background: #ddd;
}

li:last-child {
  flex-grow: 0;
 }

在此处查看演示


7
非常接近,但是我们仍然存在最后一行上的项目不是最后一个子元素的问题。我们需要一个::last-line伪元素。 - zessx

-1

更新:事实证明我理解有误,我将问题误读为仅针对列表中的最后一个项目,而不是最后一行。但是,我会将以下内容保留下来,以便未来任何遇到此问题并可能发现它有用的人。

如果我正确理解您的意思,要实现您想要的效果,您需要在所有项上设置flex-grow属性,但不包括最后一项,您可以通过将否定伪类:not():last-child伪类结合使用来实现,如下所示:

ul {
  display: flex;
  flex-wrap: wrap;
  list-style: none;
  padding: 0;
}
li:not(:last-child) {
  flex-grow: 1;
}
li {
  padding: 20px;
  margin: 10px;
  background: #ddd;
}
<ul>
    <li>lorem</li>
    <li>ipsum</li>
    <li>dolor</li>
    <li>sit</li>
    <li>amet</li>
    <li>consectetur</li>
    <li>adipisicing</li>
    <li>elit</li>
    <li>sed</li>
    <li>do</li>
    <li>eiusmod</li>
    <li>tempor</li>
    <li>incididunt</li>
    <li>ut</li>
    <li>labore</li>
    <li>et</li>
    <li>dolore</li>
    <li>magna</li>
    <li>aliqua</li>
</ul>


这使得它不会像其他孩子一样长大。 - LinPy fan

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