在一个有grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));像素的网格中取3个grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));px高的物品,并将该网格放入一个有flex-wrap: wrap;像素的弹性容器中,将推动该弹性容器具有332px的高度,而不是网格的grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));px高度(测试的 chromium 合金和Safari).

在找到解决方案之前,我只是在这个问题上猛击了一下头:设定flex-wrap: nowrap;.我确实意识到它有时也需要做大约flex-direction: columns;,但我不明白为什么这个灵活的属性会对网格产生影响.有谁能解释一下吗?也可以进行更干净的修复.

Codepen

.flex-container {
  background-color: #aaa;
  display: flex;
  flex-direction: column;
  width: 100%;
  flex-wrap: wrap;
  /*problem is here, solved with "nowrap"*/
}

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 16px;
  padding-inline-start: 0px;
  margin: 0;
}

.item {
  background-color: #cc0;
  height: 100px
}
<span>flex-container should have a height of 100px, but has 332px instead because of flex-wrap set to "wrap"</span>
<div class="flex-container">
  <ul class="grid-container">
    <li class="item"></li>
    <li class="item"></li>
    <li class="item"></li>
  </ul>
</div>

推荐答案

这与FlexBox的默认拉伸对齐方式有关.如果更改栅格容器的对齐方式,则可以看到正在发生的情况:

.flex-container {
  background-color: #aaa;
  display: flex;
  flex-direction: column;
  width: 100%;
  flex-wrap: wrap;
  /*problem is here, solved with "nowrap"*/
}

.grid-container {
  align-self: start;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 16px;
  padding-inline-start: 0px;
  margin: 0;
}

.item {
  background-color: #cc0;
  height: 100px
}
<span>flex-container should have a height of 100px, but has 332px instead because of flex-wrap set to "wrap"</span>
<div class="flex-container">
  <ul class="grid-container">
    <li class="item"></li>
    <li class="item"></li>
    <li class="item"></li>
  </ul>
</div>

网格不再是全宽的,结果是逻辑.即使你使用nowrap,你也会得到同样的结果.


诀窍在于,您的网格容器是一个弹性项,它没有明确的宽度定义,并且使用auto-fill配置.这种配置意味着您的网格需要首先获得由其环境定义的宽度,然后在此基础上定义列.换句话说,内容在定义元素的宽度方面没有任何作用.

在您的示例中,拉伸对齐定义了使元素占用所有可用空间的宽度.删除拉伸对齐将删除唯一的宽度定义,您的网格将获得可能的最小大小(一列的大小).

现在,wrapnowrap之间的区别在于算法如何工作.我会试着用简单的词语来解释它.

使用nowrap时,您使用的是单行配置

单行Flex容器(例如,带有FLEX-WRAP:NORAP的容器)在一行中布局其所有子容器,即使这会导致其内容溢出.ref

这种配置在某种程度上很简单,因为Flex容器将首先创建一行,占用所有可用空间.然后在这条线中放置元素(在您的例子中,网格容器是拉伸的),我们可以很容易地找到线和容器的最终高度.

在使用wrap时,即使最终只有one line行配置,您也可以使用多行配置

多行弹性容器(即,具有FLEX-WRAP:WRAP或FLEX-WRAP:WRAP-REVERSE的容器)跨多行打破其弹性物品,

这将使算法变得棘手,因为当我们有一个多行配置时,我们还必须确定行的大小(在您的例子中是宽度,因为您有一个列配置),我们说过网格容器没有任何显式的宽度,所以它不能调整行的大小,但是行也会使用拉伸算法来调整大小.不是同一段网格容器!

弹性线条遵循align-content属性,默认情况下,值为STRAND且FLEX ITEM服从align-items(或align-self)属性,该属性也具有拉伸默认对齐方式.因此,我们有两条嵌套的拉伸路由.

在下面,我将更新align-content,我们得到与我的第一个片段相同的行为.

.flex-container {
  background-color: #aaa;
  display: flex;
  flex-direction: column;
  width: 100%;
  flex-wrap: wrap;
  align-content: start;
  /*problem is here, solved with "nowrap"*/
}

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 16px;
  padding-inline-start: 0px;
  margin: 0;
}

.item {
  background-color: #cc0;
  height: 100px
}
<span>flex-container should have a height of 100px, but has 332px instead because of flex-wrap set to "wrap"</span>
<div class="flex-container">
  <ul class="grid-container">
    <li class="item"></li>
    <li class="item"></li>
    <li class="item"></li>
  </ul>
</div>

这种配置使算法有点复杂,因为我们首先需要找出没有拉伸对齐的线的高度( 332px),然后我们将拉伸对齐应用于增加其十字大小(其宽度)的线.这个宽度的增加也将增加网格的宽度,因为这一条也在线内拉伸,诀窍来了!网格容器有更多的空间来创建更多的列,但我们不会再次计算高度,因为它已经在前一步中完成了,因此我们保留了332px的高度.

这听起来可能有些奇怪,但双拉伸对齐与auto-fill结合在一起创造了一个复杂且非常具体的情况,在这种情况下,我们首先计算高度,稍后我们不会更新高度,以避免陷入无限循环.


为了避免这种情况,您可以使用nowrap来保留单行配置,或者显式定义网格容器的宽度(如果flex容器中不会有更多的项,width: 100%就可以完成这项工作),或者简单地go 掉flex-direction: column,这在您的情况下并不是真正需要的.但您必须将flex-grow: 1添加到栅格容器中.

拉伸对齐在横轴上工作,当使用行配置时,高度和伸缩项将在主轴上具有收缩到适合的行为,但您可以使它们增长以填充可用空间

.flex-container {
  background-color: #aaa;
  display: flex;
}

.grid-container {
  display: grid;
  flex-grow: 1;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 16px;
  padding-inline-start: 0px;
  margin: 0;
}

.item {
  background-color: #cc0;
  height: 100px
}
<span>flex-container should have a height of 100px, but has 332px instead because of flex-wrap set to "wrap"</span>
<div class="flex-container">
  <ul class="grid-container">
    <li class="item"></li>
    <li class="item"></li>
    <li class="item"></li>
  </ul>
</div>

上述配置复杂性较低,且更符合您的情况,不会产生任何"奇怪"的结果


下面是另一个相关的问题,如果你想要更多令人头疼的事情,情况也类似:flex-wrap causes children to double in height

Css相关问答推荐

如何在悬停时缓慢更改渐变 colored颜色 ?

单独.css文件中的样式不适用于Angular 元件

不了解重复-线性-渐变 colored颜色 停止

InertiaJS - Vue - Laravel:Using CSS Files

如何将CSS动画从第一列移动到第二列?

如何使我的标语(h1元素)不居中对齐?

使元素不水平滚动

如何有条件地设置元素的字体大小,只有在未明确设置父字体大小(即字体大小为继承)的情况下?

当前的 html 标签没有发生两列布局

如何在保持默认外观的同时更改 javaFX 中按钮的突出显示 colored颜色

父母是内联块,子元素有%填充=奇怪的行为

卡在 CSS 中的grid-template-columns中

有条件地覆盖 CSS 中的 AntD Select 样式

如何在连字符 (-) 等特殊字符后分词

如何在 Firefox 和 Opera 中zoom HTML 元素?

Sass 无效的 CSS 错误:预期的表达式

为什么 CSS 中的光标:指针效果不起作用

使用 CSS 使 span 不可点击

:before 和 ::before 有什么区别?

如何使用纯 CSS 创建工具提示尾部?