折叠的项目
flexbox 规范详细说明了如果一个 flex 项目通过设置 visibility: collapse 而被折叠时应该发生什么。请参阅 MDN 关于 visibility 属性的文档。规范对该行为的描述如下:
“在 flex 项目上指定 visibility: collapse 会使其成为一个*折叠的 flex 项目*,产生类似于在表格行或表格列上使用 visibility: collapse 的效果:折叠的 flex 项目会从渲染中完全移除,但会留下一个‘支柱’(strut),以保持 flex 行的交叉轴尺寸稳定。因此,如果一个 flex 容器只有一条 flex 行,动态地折叠或展开项目可能会改变 flex 容器的主轴尺寸,但保证不会影响其交叉轴尺寸,也不会导致页面其余部分的布局‘晃动’。然而,折叠后会重新进行 flex 行的换行,因此具有多行的 flex 容器的交叉轴尺寸可能会也可能不会改变。” - 折叠的项目
如果你想用 JavaScript 来控制 flex 项目以显示和隐藏内容,这种行为会很有用。规范中的例子就演示了这样一种模式。
在下面的实时示例中,不换行的 flex 容器包含一行三个 flex 项目,它们被设置为等尺寸伸缩。第三个项目有多行内容,使得容器变高。align-items 的默认值是 normal;对于 flex 项目,normal 的行为与 stretch 相同,所以所有项目默认都会拉伸,以填充容器的交叉轴高度。
创建交叉轴尺寸的项目被设置为 visibility: collapse,这会根据浏览器的不同,折叠或隐藏该 flex 项目。无论哪种情况,flex 容器都会保留一个交叉轴尺寸的*支柱*,即使它不可见。这样,如果该项目变为可见,单行 flex 容器的交叉轴尺寸将不会改变。如果你从 CSS 中移除 visibility: collapse 或将值更改为 visible,你会看到项目出现,主轴空间在未折叠的项目之间重新分配,而交叉轴尺寸保持不变。
注意:下面的示例请使用 Firefox,因为其他主流浏览器会将 collapse 处理为 hidden。
html
css.box {
border: 2px dotted rgb(96 139 168);
display: flex;
width: 600px;
}
.box > * {
flex: 1 1 200px;
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
}
.collapse {
visibility: collapse;
}
p:has(:checked) + div .collapse {
visibility: visible;
}
以上是一个单行、不换行的 flex 容器,其固定尺寸为 600px,因此无论项目是可见还是折叠,宽度都相同。重要的是要理解,虽然容器保留了折叠项目交叉轴尺寸的支柱,但主轴尺寸并未保留。多行 flex 容器在从渲染中移除折叠项目后会重新进行换行。折叠项目在主轴方向上留下的新空间可能会导致未折叠的项目被放置在与未折叠时不同的行上。因为每一行都像一个独立的单行 flex 容器一样进行布局,其构成在折叠后可能会改变,所以它的交叉轴尺寸也可能改变。
下面的例子展示了这种行为。第三个 flex 项目被折叠,因此它在主轴上不占用任何空间(行内尺寸为 0)。折叠时,它的支柱位于第一行第四个项目之后,第一行的高度足以容纳第三个项目本应有的三行文本。然后,如果你取消折叠该项目(例如,通过移除 collapse 类),第一行将不再有足够的水平空间容纳第五个项目,它会移动到第二行。这导致第二行变高以适应其新成员的两行文本,而最后一个 flex 项目被推到了新的一行。由于第二行变高和新增了第三行,flex 容器比之前高了很多。
注意:下面的示例请使用 Firefox,因为其他主流浏览器会将 collapse 处理为 hidden。
html
css.box {
border: 2px dotted rgb(96 139 168);
width: 500px;
display: flex;
flex-wrap: wrap;
}
.box > * {
padding: 10px;
border: 2px solid rgb(96 139 168);
border-radius: 5px;
background-color: rgb(96 139 168 / 0.2);
flex: 1 1 auto;
min-width: 50px;
}
.collapse {
visibility: collapse;
}
p:has(:checked) + div .collapse {
visibility: visible;
}
如果这给你的布局带来了问题,可能需要重新考虑结构,例如,将每一行放入一个单独的 flex 容器中,这样它们就不会换行了。