在flex容器中实现等高行

192

如您所见,第一行中的list-items具有相同的height。但是第二行中的项目具有不同的 heights。 我想让所有项目具有统一的height,是否有办法在不设置fixed-height的情况下仅使用flexbox来实现?

enter image description here

以下是我的代码

.list {
  display: flex;
  flex-wrap: wrap;
  max-width: 500px;
}
.list-item {
  background-color: #ccc;
  display: flex;
  padding: 0.5em;
  width: 25%;
  margin-right: 1%;
  margin-bottom: 20px;
}
.list-content {
  width: 100%;
}
<ul class="list">
  <li class="list-item">
    <div class="list-content">
      <h2>box 1</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h1>h1</h1>
    </div>
  </li>
</ul>


一种方法是在高度可能会变化的元素上设置高度。 - onmyway133
为什么不在灰色框上使用最小高度? - user31782
16个回答

131

答案是否定的。

原因在于flexbox规范提供了明确的解释:

 

6. Flex Lines

    

在多行flex容器中,每行的交叉轴尺寸是包含该行上所有flex项目所需的最小尺寸。

换句话说,在基于行的flex容器中有多行时,每行(“交叉轴尺寸”)的高度是包含该行上所有flex项目所需的最小高度。

然而,在CSS Grid Layout中可以实现等高行:

否则,请考虑使用JavaScript替代方法。


CSS Grid现在使用起来安全吗? - Alexander Kim
https://caniuse.com/ - Chris Pillen
@AlexanderKim 请查看此 Stack Overflow 帖子:CSS Grid 的浏览器支持 - Michael Benjamin
你可以将以下代码设置为: 对于列表元素,height: 100%,然后高度等于该行中最高的元素。 - nojitsi

92

现在你可以通过display: grid实现这一点:

.list {
  display: grid;
  overflow: hidden;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 1fr;
  grid-column-gap: 5px;
  grid-row-gap: 5px;
  max-width: 500px;
}
.list-item {
  background-color: #ccc;
  display: flex;
  padding: 0.5em;
  margin-bottom: 20px;
}
.list-content {
  width: 100%;
}
<ul class="list">
  <li class="list-item">
    <div class="list-content">
      <h2>box 1</h2>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit.</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>

  <li class="list-item">
    <div class="list-content">
      <h3>box 2</h3>
      <p>Lorem ipsum dolor</p>
    </div>
  </li>
  <li class="list-item">
    <div class="list-content">
      <h1>h1</h1>
    </div>
  </li>
</ul>

尽管网格本身不是flexbox,但它的行为非常类似于flexbox容器,并且网格内部的项可以弹性展开。 网格布局在需要响应式网格时也非常方便。也就是说,如果您希望网格每行具有不同数量的列,那么您只需更改grid-template-columns即可。
grid-template-columns: repeat(1, 1fr); // 1 column
grid-template-columns: repeat(2, 1fr); // 2 columns
grid-template-columns: repeat(3, 1fr); // 3 columns

等等...

您可以与媒体查询混合使用,并根据页面大小进行更改。

可悲的是,浏览器仍不支持容器查询/元素查询(开箱即用),以便根据容器大小而不是页面大小更改列数(这对于可重复使用的Web组件非常有用)。

有关网格布局的更多信息:

https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout

支持跨浏览器的网格布局:

https://caniuse.com/#feat=css-grid


2
这种“可以做到”的方法正是我喜欢的!同时感谢提供工作示例。 - hananamar
1
这并不实现与flexbox wrapping相同的行为。此外,问题要求使用flexbox来回答。 - Andy
4
正如接受的答案已经说过的,你不能使用 flexbox 来实现这一点(不使用 JavaScript)。我还确保说了它真的不是 flexbox(“虽然网格本身不是 flexbox...”),并且我并没有说行为与 flexbox 完全相同(这是显而易见的),但它非常相似并解决了所提出的问题(除了它不是 flexbox),更重要的是,它可能会为其他寻找类似方法的用户解决类似的问题。此外,项目可以采用 flexbox 布局(而不是期望表项的表格布局,例如)。 - Lucas Basquerotto

77

Flexbox:如何使所有弹性项目高度相同?

在子元素中

align-self: stretch;

或者在父容器中

justify-content: stretch;

6
我无法相信我不得不滚动查看两个更高评分的评论,声称使用flex不可能实现,应该使用grid。显然,grid才是正确的答案。 - Jules Colle
11
由于它无法使用flex-wrap: wrap。 - flappix
请原谅我@flappix,但我不确定你在说什么。虽然我只是个新手,但使用“flex-wrap: wrap”对我来说完美地解决了问题。非常感谢您的回答,user1438038。 - José Guedes
@JoséGuedes 我在谈论这个 https://jsfiddle.net/brukmo71/1/ 在这种情况下它不起作用,第一行比其他行高。 - flappix
1
这个答案是使用flex时的最佳选择,因为在单行中,所有元素的高度都将保持一致。如果你确实需要整个布局中的每个元素的高度完全相同,那么使用display: grid(而不是flex)和align-items: stretch是下一个最佳的CSS选项。 - undefined

18

使用flexbox可以解决水平方向问题:

.flex-list {
    padding: 0;
    list-style: none;
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    justify-content: center;
    gap: .5rem;
}
.flex-list li {
    width: 120px;
    padding: .5rem;
    border-radius: 1rem;
    background: yellow;
}
<ul class="flex-list">
  <li>title 1</li>
  <li>title 2</li>
  <li>title 3<br>new line</li>
  <li>title 4<br>new line</li>
  <li>title 5<br>new<br>line</li>
  <li>title 6</li>
</ul>

或者使用网格布局来解决水平和垂直问题:

.grid-list {
   padding: 0;
   list-style: none;
   display: grid;
   grid-auto-columns: 1fr;
   grid-auto-rows: 1fr;
   grid-template-columns: repeat(3, 1fr);
   gap: .5rem;
}
    
.grid-list li {
   padding: .5rem;
   border-radius: 1rem;
   background: yellow;
}   

.grid-list li:last-child {
   grid-column-start: 2;
}  
<ul class="grid-list">
    <li>title 1</li>
    <li>title 2<br>new<br>line</li>
    <li>title 3<br>new line</li>
    <li>title 4<br>new line</li><li>title 5</li>
    <li>title 6<br>new<br>line</li>
    <li>title 7</li>
   </ul>


2
我认为当项目垂直堆叠时,这并不能提供相等的高度。 - workwise
1
这对我来说很有效,使用Angular Material卡片与divs,但将容器更改为ul和li卡片,完美。谢谢!我制作了一个https://codepen.io/marcbate/pen/JjmeNPL?editors=1100。 - MarcBate

5

2
这似乎在父元素高度固定的情况下有效(在Chrome和Firefox中测试过):
.child {
        height    : 100%;
        overflow  : hidden;
}

.parent {
        display: flex;
        flex-direction: column;
        height: 70vh; // ! won't work unless parent container height is set
        position: relative;
}

如果由于某些原因无法使用网格,也许这就是解决方案。

2

当使用flex-direction: row时,您可以在项目上使用height: auto来实现:

.parent {
  display: flex;
  flex-direction: row;
}
.item {
  height: auto;
}

谢谢,这就是我所缺少的。我设置了height: 100%;,但它没有起作用。 - undefined

1

如果您知道正在映射的项,您可以逐行完成此操作。 我知道这是一个解决方法,但它有效。

对于我来说,我每行有4个项目,因此我分成了两行,每行有4个项目,每行的高度为50%,去掉flex-grow,在一个<div>中有<RowOne /><RowTwo />,并使用flex-column。 这就可以解决问题了。

<div class='flexbox flex-column height-100-percent'>
   <RowOne class='flex height-50-percent' />
   <RowTwo class='flex height-50-percent' />
</div>

1

你可以通过以下方式实现:

align-items: stretch;

这将使每个项目的高度都延伸到 flex 中具有最大高度的元素的高度。


1

你应该在 flex 布局中使用 justify-content:stretchalign-items:stretch 属性,这样可以使每个元素的高度相等。


在我的 Ubuntu 18.04.x 版本的 Chrome 中不是这样的。高度是不同的。 - Eugene Gr. Philippov
可能适用于Chrome的较新版本,我的版本是93.0.0。 - Himanshu Singh Chauhan

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