何时使用 CSS Grid 以及何时使用 Flexbox 进行多行布局
介绍
Flexbox 和 CSS Grid 都是 CSS 内置的强大布局技术。它们有很多共同点。对于大多数任务,例如垂直居中,我可以选择其中任何一种。但在某些情况下,其中一种才是完成任务的唯一方法。
考虑到当前的网络标准,哪一个比另一个更好?
如果 Grid 或 Flexbox 都可以,我现在会选择 Grid。我会在讨论一些不同的多行场景后解释原因。
差距
很快就会有一种统一的方法来在子项之间应用一致的间距,如父项所定义:gap
。因此,gap: 5px
不会影响外部边距,只会影响内部项之间的间距。
这个方法的灵感来源于 Grid 的grid-gap
属性,并最终将取代它。遗憾的是,除了 Firefox 之外,在 Flexbox 的多行(环绕)项目上实现相同效果的唯一方法是使用负边距技巧。即所有子项目都获得等于间隙一半的边距。然后,为了计算外部的额外空间,容器会获得一个相同值乘以 -1 的边距。只有当只有单行(非环绕式 Flex 容器)时,才能在项目上使用:first-child
和来计算额外空间。:last-child
对于多行网格容器,只需应用grid-gap
。
获胜者:网格,但希望gap
弹性布局能很快被添加到 Chrome 和 Safari 中。
一致大小调整 vs 自动大小调整
如果您在两个方向上都有轨道(多列和多行布局),那么您的选择取决于子项目相对于其他项目的宽度。
如果您希望所有项目均匀排列并垂直堆叠,请使用网格。
如果您希望项目保留其自然宽度并且不垂直排列,请使用 Flexbox。
Grid 的代码需要repeat()
在容器的属性上定义一个函数grid-template-columns
。该repeat
函数接受两个值。第一个值对我们来说是 eitherauto-fill
或auto-fit
。第二个函数是一个minmax
函数,它接受一个固定单位的值和另一个固定或相对值。
总体来说可能看起来像这样:
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
这将为每个项目赋予 200px 的基本宽度,并根据需要进行扩大。
对于 Flexbox,只需添加flex-wrap: wrap
。
优胜者:取决于用例,但 Flexbox 要简单得多。🙃
容器控制与项目控制
在某些情况下(例如两个组件之间的边界),您只想修改父容器的 CSS 或子容器的 CSS。
如果您可以控制父元素,请使用 Grid,它使用grid-template-*
和定义子元素grid-auto-*
。
如果您可以控制子元素,请使用 Flexbox,其中子元素可以定义自己的flex-basis
。
如果由于其他原因必须使用 Flexbox,您仍然可以在父级上定义一个 CSS 变量,该变量将由子级继承。
优胜者:取决于具体使用场景,但 Flexbox 因其多功能性而占一分。我个人喜欢尽可能地在一个地方控制父元素上的所有项目,所以 Grid 也占一分。
嵌套布局
仅在 Firefox 中实现的一项杀手级 CSS 网格功能是subgrid
。这允许子网格项根据与顶级父级相同的轨道定义来定义其网格子项。
如果您有一组项目,它们内部被拆分成顶部和底部两部分,且内容量可变,则可以auto
在顶层定义两个重复的网格轨道。然后,中间层的子项目分别占据两个重复行。然后,它们将轨道定义向下传递,使顶部部分接收一个auto
轨道,底部部分接收另一个轨道。现在,在所有项目中,拆分将在同一个位置进行,因此它们在内部都对齐了。
获胜者:网格,但在 Firefox 以外的任何浏览器中,布局仍然不均匀。
结论
对于大多数其他用例,尤其是在单向使用单轨道且项目之间没有间距的情况下,我都愿意使用其中任何一种。这适用于需要垂直居中和相对大小调整的情况。
但是我发现,当我在父元素的一个位置定义子元素时,更容易推断它们应该如何布局 - 因此大多数情况下 Grid 会胜出。
总冠军:网格,但要知道它的局限性!
正如我提到的,Firefox 在这方面处于领先地位。请⭐️/抄送自己关于 Chromium 和 WebKit 上这些问题,以便未来让 Flexbox 和 Grid 更加强大!
-
gap
对于 Flexbox(Chromium):https://bugs.chromium.org/p/chromium/issues/detail? id=762679 -
gap
对于 Flexbox(WebKit):https://bugs.webkit.org/show_bug.cgi? id=206767 -
subgrid
(Chromium):https://bugs.chromium.org/p/chromium/issues/detail? id=618969 -
subgrid
(WebKit):https://bugs.webkit.org/show_bug.cgi? id=202115