这与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
配置.这种配置意味着您的网格需要首先获得由其环境定义的宽度,然后在此基础上定义列.换句话说,内容在定义元素的宽度方面没有任何作用.
在您的示例中,拉伸对齐定义了使元素占用所有可用空间的宽度.删除拉伸对齐将删除唯一的宽度定义,您的网格将获得可能的最小大小(一列的大小).
现在,wrap
和nowrap
之间的区别在于算法如何工作.我会试着用简单的词语来解释它.
使用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