CSS Grid 是否取代 Flexbox?

Avatar of Robin Rendle
Robin Rendle

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

不。嗯,大部分情况下不。

Grid 比 Flexbox 新得多,并且浏览器支持度略低。因此,如果人们想知道 CSS Grid 是否要取代 Flexbox,这是完全合理的。

总结一下

  1. Grid 可以做 Flexbox 做不到的事情。
  2. Flexbox 可以做 Grid 做不到的事情。
  3. 它们可以一起工作:网格项目可以是 Flexbox 容器。Flex 项目可以是网格容器。

尽管 Grid 比较新,但我们有 大量关于它的文章,包括一篇 入门文章,一篇关于 以多种方式完成基本布局 的文章,以及一篇 完整指南

如果您还没有听到号角声,2017年3月 是 Grid 的标志性月份。它在 Chrome、Opera、Firefox 和 Safari 中发布,完全没有前缀,并且可以使用。即使是 Edge 也支持它,尽管它使用的是较旧版本的规范,您可以通过使用 Autoprefixer 获得一些支持。

所以。

Grid 是否取代 Flexbox?

一开始看起来有点复杂。特别是如果您刚开始掌握 Flexbox 的奇怪、陌生的语法。现在又需要学习另一种语法?真是令人头疼。

以下是 Grid 比 Flexbox 更擅长的一些方面

  • 制作整个页面布局。即使考虑到 布局性能原因,它也更适合此目的。
  • 制作真正的网格。例如,具有 Y 间隙的 X 列,自制框架之类的东西。grid-gap 非常棒,因为间距是网格系统的主要痛点。
  • 需要 更少的媒体查询干预,并具有强大的功能,如自动布局、minmax()repeat()auto-fill。这里有一个 好主意

还有一个非常重要的方面:Grid 可以二维定位元素。既可以是列,也可以是行。这是第一次。Rachel Andrew 曾经 非常清楚地说明了这一点

Flexbox 本质上用于在一维中布局项目——在一行或一列中。Grid 用于在二维中布局项目——行和列。

让我们看一些演示。

假设我们正在构建一个水平导航组件——这是 Flexbox 的完美用例,因为它仅在一个方向上设置内容。在 Chris 下面的演示中,您可以修改这些属性,并了解 Flexbox 的强大功能

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 使用 Flexbox 和 SVG 图标的栏导航

但在某些情况下,应将这些 flexbox 属性(如 justify-contentalign-items)与 Grid 属性结合使用。例如,请查看此演示

查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Flexbox 和 Grid – 第一个演示

首先,我们创建了一个设置为 display: flex; 的 .wrapper。这样,我们就可以在 .grid 上设置最大宽度,并使用 justify-content: center; 将其放置在视口中央。然后,我们可以创建具有正确列数的网格

.wrapper {
  display: flex;
  justify-content: center;
}

.grid {
  display: grid;
  max-width: 800px;
  grid-template-columns: 1fr 2fr;
}

这仅仅是第一步。

现在让我们使该 .ad 占据网格的整行。我们可以通过专门定位我们的 来实现

而不影响网格其他子元素

.ad {
  grid-column-start: 1;
  grid-column-end: 3;
}

我们在上面的代码中说的是“从第一列开始此 div,并在最后一列结束。” 它应该看起来像这样

查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Flexbox 和 Grid

此外,假设我们始终希望我们的广告块是第一行的两倍大小——我们可以做到!我们只需要使用 grid-template-rows 属性即可

.grid {
  display: grid;
  max-width: 800px;
  grid-template-columns: 1fr 2fr;
  grid-template-rows: 1fr 2fr 1fr;
}

这相当于说:“网格中有三行。始终确保第二行是第一行和第三行大小的两倍。”换句话说,我们在行与其他行之间创建关系,同时还定义网格中的列数!

查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Flexbox 和 Grid

使用 CSS Grid,我们可以同时水平(使用 grid-template-columns)和垂直(使用 grid-template-rows)设置关系。另一方面,Flexbox 只能执行垂直或水平布局(使用 flex-direction),但这并不意味着我们应该放弃它。

可能令人困惑:“2D” Flexbox 布局

可能有点令人困惑的是,在 Flexbox 中创建多维布局并非不可能。例如

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 Flexbox 的“网格”

那里肯定有行和列,甚至有一个跨越多个列的最终元素。它易于构建且灵活。它是通过在容器上启用 flex-wrap、使子元素的 flex-basis 成为容器宽度的 1/3 以及在需要时允许 flex-grow 拉伸子元素来实现的。(flex 属性是 flex-growflex-shrinkflex-basis 的简写。)

这并没有错,这只是执行此类操作的一种方法,您可能可以争辩说它不太直观且适应性不强。

可能令人困惑:“1D” 网格布局

Grid *可以*执行 2D 布局,这意味着定义 grid-template-rowsgrid-template-columns,但它不必同时使用两者。这是一个仅使用它在一行中水平放置框的演示

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 使用 Grid 创建简单列

这也没有错。实际上,您可以很容易地争辩说,这比使用 Flexbox 更易于理解和更简洁地表达。例如,子元素根本不需要任何布局属性。但是您也可以争辩说,像这样的纯 1D 布局在 Flexbox 中更强大,因为 Flexbox 允许我们更轻松地移动这些元素(例如,将它们全部移动到一侧或另一侧、更改其顺序、均匀地间隔它们等)。

关于嵌套

再次强调一下!

这一点需要记住:网格项目可以是 Flex 父级。

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 使用 Grid 创建简单列

并且,Flex 项目可以是网格父级

查看 CodePen 上 Chris Coyier (@chriscoyier) 编写的 使用 Grid 创建简单列