CSS3 新增布局三剑客之 Grid Layout
一, 前言
相比较 Multi-Columns Layout 和 Flexible Box Layout,Grid Layuot 更像是两者的结合, 当然这里并不是说 Grid Layout 可以取代二者.
另外 Grid Layout 与当前非常火热的 Flexible Box Layout 有一个本质上的区别就是维度不一样. 在使用 Flexible Box Layout 时, 我们只能通过 flex-direction 定义主轴沿着某一方向, 而在 Grid Layout 中截然不同.
二, 核心用法
下面一步步去了解 Grid Layout 的核心用法:
1, 宏观角度
宏观上可以将 Grid Layout 看成由行和列组成, 这一点可以类比 html 中的 table 标签, 接下来用 Grid 语法声明一个 3 行 3 列的结构.
- .grid {
- display: grid;
- width: 300px;
- height: 300px;
- margin: 0 auto;
- grid: repeat(3, 1fr) / repeat(3, 1fr);
- }
- .grid> div:nth-child(odd) {
- background-color: #f5f5f5;
- }
- .grid> div:nth-child(even) {
- background-color: #eee;
- }
通过设置 display 属性为 grid 或者 inline-grid, 可以使得该元素变成 Grid 布局容器, 这基本是新增布局声明的一个通用套路.
上述 grid 属性是一个复合属性, 等价下面的代码.
- .grid {
- /*
- grid: grid-template-rows / grid-template-columns
- */
- grid-template-rows: repeat(3, 1fr);
- grid-template-columns: repeat(3, 1fr);
- }
fr 是 Grid Layout 中新增的单位, 可以类比 Flexible Box Layout 中的 flex-grow 属性.
上述九宫格中的每一个小格子在 Grid 中有一个专门的术语 -- Grid Cell.
2, 微观角度
从微观的角度去看 Grid Layout, 首先你需要了解另一个术语 -- Grid Line.
不知道读者们有没有看过制作豆腐的过程, 其中有一个步骤是用线将整块的豆腐割开, 那条线和上述的 Grid Line 是一样一样的.
那么我们前面所说的行与列就需要用一个更专业的术语来描述 -- Grid Track.
Grid Track 实际上就是相邻的两条 Grid Line 所形成的区域.
在 Grid Layout 中是看不见 Grid Line 的, 但是可以使用它, 它默认是数字编号的形式, 还记得上面的九宫格布局吗? 通过设置 display 和 grid 属性, 只是将容器划分了结构, 但是并没有设置子元素的放置方式, 幸好 Grid Layout 会为每一个子元素设置一个默认位置, 例如第一行第一列的元素会这样设置.
- /* grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end */
- grid-area: 1 / 1 / 2 / 2;
上述的数字就是 Grid Line 的编号, 并且它还支持自定义命名.
- .grid {
- position: relative;
- margin: 100px auto;
- width: 500px;
- height: 500px;
- display: grid;
- grid: [line-row-1]1fr[line-row-2]1fr[line-row-3]1fr[line-row-4] / [line-col-1]1fr[line-col-2]1fr[line-col-3]1fr[line-col-4];
- }
- .grid> div:nth-child(1) {
- grid-area: line-row-1 / line-col-1 / line-row-4 / line-col-3;
- }
3,Grid Area
Grid Area 也是一个比较重要的术语, 它主要由一个或者多个 Grid Cell 组成. 前面的例子中, 我们已经看到可以通过 Grid Line 为 Grid Area 分配空间, 并且它还有另一种使用的方式.
- .grid {
- position: relative;
- margin: 100px auto;
- width: 500px;
- height: 500px;
- display: grid;
- grid: "first first second" "first first fouth" "first first third";
- }
- .grid> div:nth-child(1) {
- grid-area: first;
- }
- .grid> div:nth-child(2) {
- grid-area: second;
- }
- .grid> div:nth-child(3) {
- grid-area: third;
- }
- .grid> div:nth-child(4) {
- grid-area: fouth;
- }
同样是上述的例子, 我们可以这样放置子元素, 是不是特别的友好.
4, 绝对定位在 Grid Layout 中的表现
绝对定位大家应该很熟悉, 其位置主要由包含块或者初始化包含块决定, 通常我们都是通过设置父级元素的 position 属性来确定包含块, 但是在 Grid Layout 中可以通过 grid-area 属性达到同样的效果.
- .grid {
- position: relative;
- width: 400px;
- height: 400px;
- margin: 100px auto;
- display: grid;
- grid: repeat(2, 1fr) / repeat(2, 1fr);
- border: 1px dashed red;
- padding: 10px;
- }
- .demo1 {
- grid-area: 2 / 1 / 3 / 2;
- position: absolute;
- top: 30px;
- left: 30px;
- width: 100px;
- height: 100px;
- background: red;
- }
5, 其它
理解上面介绍的几个术语和用法之后, 基本上 Grid Layout 也没有那么神秘了. 另外, 例如 Grid item 之间的间隙以及它们的排列方式, 基本上和 Flexible Box Layout 大同小异.
不过 Grid Layout 中还有很多好玩的知识点, 例如 margin 凹陷的特性在 Grid Layout 中并不会发生. 这些就留给读者自己去探索吧.
三, 最后
为什么会起这个标题呢? 主要是因为现在大部分的 UI 组件库基本上都提供 grid 组件, 就拿比较流行的 Bootstrap 组件库来说, grid 组件的实现:
.row 设置行,.col-* 设置一个百分比宽度的列;
.row 通过负外边距抵消容器的 padding;
.col 通过左右内边距实现元素之间的间隙效果;
通过媒体查询设置断点 (breakpoints) 实现响应式的布局;
而 CSS3 新增的这个 Grid Layout 相比较这些实现方式, 可以说是非常优秀了. 相信不久我们可以告别 Grid-Framework, 只有一个 CSS3 的 Grid Layout.
参考资料
W3C Grid Layout https://www.w3.org/TR/CSS-grid-1/
大漠老师的《使用 CSS Grid 的九大误区》里面整理了很多参考资料
上述所有用例的代码
来源: https://juejin.im/post/5bafb20f518825573058337d