• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

Flexbox 和 CSS Grid:你应该使用哪个以及何时使用?

flexboxcss Grid 是近年来成为主流的两个 CSS 布局模块。然而,何时使用哪个是另一个问题。

两者都允许我们创建以前只能通过应用 CSS hack 和/或 javascript 才能实现的复杂布局。Flexbox 和 CSS Grid 有很多相似之处,很多布局都可以用两者来解决。让我们看看我们是否可以澄清什么时候应该使用 Flexbox 以及什么时候应该使用 CSS Grid。

行业回顾

CSS Grid 与 flexbox 的争论是目前 CSS 社区中最热门的话题。如果您关注行业新闻,您会看到最近出现了许多很棒的文章,例如:

  • 早在 2016 年, Rachel Andrew 就已经在博客上讨论过这个问题 ,后来继续更详细地讨论它。

  • 上个月,Chris Coyier 启动了一个病毒式的 Twitter 线程 ,最终在一篇较长的文章中出现了一些关于 CSS-Tricks 的很酷的代码示例。

  • Michelle Barker 还通过在她流行的 CSS {In Real Life} 博客中撰写另一篇优秀的Grid vs flexbox 文章来回应 Chris 的 Twitter 帖子 。

  • MDN 社区创建了一些关于Grid 和 flexbox之间基本区别的详尽文档 ,这是目前关于该主题的最佳可用文档。

您还可以在整个网络上找到许多其他相关的博客文章、文章、视频和讨论。由于该主题将来可能会保持相关性,因此我建议您阅读上面的一些文章并就该问题制定自己的立场,因为还没有一成不变的。

这是另一个观点。

一维与二维

最重要的是要知道 flexbox 是一维的,而 CSS Grid 是二维的。Flexbox 沿水平轴或垂直轴对项目进行布局,因此您必须决定是基于行还是基于列的布局。


Flexbox 和 CSS Grid:你应该使用哪个以及何时使用?  第1张
flexbox 的横轴总是垂直于主轴。 

flex 布局也可以包含在多行或多列中,并且 flexbox 根据其内容和可用空间将每一行或列视为一个单独的实体。

另一方面,CSS Grid 允许您沿着两个轴工作:水平和垂直。网格允许您创建二维布局,您可以在其中将网格项精确地放置到由行和列定义的单元格中。

这就是 W3C 希望我们使用 flexbox 和 Grid 的方式,但是实践经常凌驾于理论之上,并不是每个人都喜欢一维与二维的叙述。例如,Chris Coyier 在上述文章中发表了以下声明:

“我不是网格与 flexbox 的“1D”与“2D”差异化的世界上最大的粉丝,只是因为我发现网格的大部分日常使用都是“1D”,它非常适合. 我不希望有人认为他们必须使用 flexbox 而不是网格,因为网格仅在您需要 2D 时才出现。尽管 2D 布局在网格中是可能的,但这是一个很大的区别,尽管在某些方面它不在 flexbox 中。”

而且,这就是 CSS 在现实生活中的工作方式。实际上,我们也可以使用 flexbox 创建二维布局(由于它的包装能力)和使用 CSS Grid 的一维布局(由于它的自动放置能力)。

尽管 flexbox 最初不是用于构建网格,但它经常以这种方式使用。最好的例子是 Bootstrap 4 的基于 flexbox 的网格系统。所有 Bootstrap 4 站点都使用 flexbox 来完成 二维布局,包括行和列。并且,还有其他流行的工具,例如Flexbox Grid可以做到这一点。

用例

关于这两个布局模块最常见的误解是 Grid 用于整页布局,而 flexbox 用于较小的组件。根本不是这种情况。上面提到的所有作者都警告不要使用这种方法,因为它会严重限制可能性。您需要根据具体情况单独评估每个布局,以选择更好的选项。

专注于内容放置:CSS Grid

CSS Grid 专注于精确的内容放置。每个项目都是一个网格单元,沿水平轴和垂直轴排列。如果您想准确控制布局中项目的位置,CSS Grid 是您的最佳选择。Grid 模块的W3 文档断言:

“它为作者提供了一种机制,可以使用一组可预测的大小行为将用于布局的可用空间划分为列和行。然后,作者可以将其应用程序的构建块元素精确地定位和调整到由这些列和行的交叉点定义的网格区域中。”

使用 flexbox,很难预测某些视口的行为,您会得到令人惊讶的结果。当然,您可以设置 flex 项的宽度和高度或使用该calc()功能,但这样您就失去了 flexbox 的主要吸引力:灵活性。

这不是 CSS Grid 的情况。它具有诸如grid-template-rows和之类的属性以及诸如分数单位grid-template-columns之类的实用程序,可让您精确计算所有内容。因此,Grid 特别适用于创建不寻常的布局,例如损坏的、不对称的和重叠的布局。

CSS Grid 还可以在不使用媒体查询的情况下创建响应式布局。这个想法来自 Heydon Pickering,他最近发布了一段关于算法布局的YouTube 视频。他介绍了一种简单的 Grid 技术,可以让网格单元包裹并适应任何视口大小


.container {  

display: grid;  

grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));  

grid-gap: 1rem;

}

尽管布局基于可用空间进行换行,但它仍然不像 flexbox 那样具有内容感知能力,因为项目内的内容不会灵活地伸展:

See the Pen  Wrapping layout with CSS Grid by Envato Tuts+ (@tutsplus)  on CodePen.

关注内容流:Flexbox

Flexbox 专注于内容流而不是内容放置。弹性项目的宽度(或高度)由项目的内容决定。Flex 项目根据其内部内容和可用空间来增长和缩小。这就是 W3C 的flexbox 文档如何 解释布局模块的目标:

“... (flexbox) 获得了简单而强大的工具,用于以 Web 应用程序和复杂网页通常需要的方式分配空间和对齐内容。”

简而言之,flexbox 使您能够灵活地分配空间和对齐项目。让我们看看 Heydon 的网格在 flexbox 中的样子。以下代码为每个 flex 项目添加了 0.5rem 的边距(因为 flexbox 没有 gap 属性,我们需要使用负边距 hack)。


.container {  display: flex;  flex-wrap: wrap;  margin: -0.5rem;}

.item {  margin: 0.5rem;}

正如您在下面看到的,第一个具有长内容的 flex 项目会根据需要延伸:

See the Pen  Content-aware wrapping layout with flexbox by Envato Tuts+ (@tutsplus)  on CodePen.

当然,您可以使用widthorflex-basis属性制作固定宽度的弹性项目。但是,如果这样做,您将失去 flexbox 的内容感知能力,这是它存在的主要原因。您还可以在上面看到 flexbox 独立处理每一行。根据其中的文本数量,不同的行以不同的方式对齐弹性项目。这里没有列,这不是网格而是一维布局。

Flexbox 还允许您决定当屏幕空间过多或空间不足时您的内容应该如何表现。我在关于flexbox sizing的文章中详细介绍了该主题。使用flex-grow和flex-shrink属性,您可以实现完全流畅的布局,优化每个视口大小的弹性项目的分配。

flexbox 还有其他典型的用例,例如居中项目、调整列表的最后一项、将页脚粘贴到页面底部以及创建响应式菜单。您可以在MDN 文档中找到更多 flexbox 使用示例。

浏览器支持

Flexbox 有相当好的浏览器支持,而IE11- 和 Edge 15- 不支持CSS Grid 。

Flexbox 和 CSS Grid:你应该使用哪个以及何时使用?  第2张
CSS 灵活框布局模块(截至撰写本文时)
Flexbox 和 CSS Grid:你应该使用哪个以及何时使用?  第3张
CSS 网格布局(截至撰写本文时)

文章经常推荐使用 flexbox 作为 CSS Grid 的后备,但是许多开发人员认为它太麻烦,宁愿只使用 flexbox 创建他们的布局。

但是 flexbox 也不是完美的。它在 GitHub 上的 Flexbugs 存储库中收集了几个问题(带有针对错误的跨浏览器解决方法)。如果您在使用 flexbox 时遇到问题,值得查看此列表,因为您可能会找到解决问题的方法。

准备战斗!

flexbox 与 CSS Grid 的问题没有明确的答案,取决于许多不同的因素。不要坚持一个或另一个,但要始终考虑哪个更好地为您的目标服务。你还可以结合 flexbox 和 CSS Grid 来解决复杂的布局,比如这个很酷的卡片 UI:

See the Pen  Solving Problems With CSS Grid and Flexbox: The Card UI i by Envato Tuts+ (@tutsplus)  on CodePen.

文章目录
  • 行业回顾
  • 一维与二维
  • 用例
    • 专注于内容放置:CSS Grid
    • 关注内容流:Flexbox
  • 浏览器支持
  • 准备战斗!