跳到主要内容

网格布局

​​​​网格 grid 是二维布局,它的功能有:

  • 可以用行列来定义网格,可以设置行列的大小,或者让它们根据内容自行调整。

  • 容器的直接子元素会被自动放入网格中。或者放在指定的位子中。

  • 网格中的线条和区域可以被命名来更好地放置物品。

  • 闲置空间在网格轨道( track )之间分配。

  • 物品可以在网格中进行对齐。

相关概念

网格线 Grid lines

网格线横纵分布,从 1 开始编号(按照书写顺序)。

网格轨道 Grid tracks

轨道是两条网格线之间的空间(注意不是单元格)。

网格单元格 Grid cell

网格区域 Grid area

由多个单元格组成的矩形区域。

间隔 Gaps

网格轨道间的间隙。

网格容器 Container

.container {
display: grid;
}

网格物品 Item

<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

设置行列

​创建一个两行三列、10px 间隙的网格:

.container {
display: grid;
/* 这里三个值对应三列 */
grid-template-columns: 5em 100px 30%;
grid-template-rows: 200px auto;
gap: 10px;
}

网格案例

打开 DevTools ,选中一个网格,然后在选项卡里找到布局(layout)-> 显示行号,同时勾选上网格覆盖中的目标网格容器,就可以看到网格线编号了。

fr 单位只在网格布局中使用,和弹性盒子中的 flex 权重分配类似

grid-template-xxx

grid-template-xxx 上可以用的关键词及函数:

  • auto 自行伸展;

  • min-content 尽可能的小;

  • max-content 尽可能的大,可能会导致溢出,因为字符串不会换行;

  • fit-content(x) 大小先随内容伸展,当网格轨道大小超过 x 会自动换行;

  • minmax() 可以用这个函数设置轨道的最小最大值,参数可以是关键词;

  • repeat(n, size) 用这个快速创建相同的列;

    第一个参数是数量,第二个是大小。一行中可以重复用这个函数。

自动放置​​

如果你不想指定列的数量,可以用 auto-fillauto-fit 关键词作为 repeat 的第一个属性值。

比如,自动填充,每列 200px :

grid-template-columns: repeat(auto-fill, 200px);

又比如,每列自动伸展,且最小值应当为 200px :

grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));

auto-fitauto-fill 主要区别在于只有单行内容(子元素宽度之和小于容器宽度)的情况下,auto-fit 会自动横向伸展容器,而 auto-fill 会保持最小值。当网格轨迹被完全填充时,这两个关键词是没区别的。

自动放置

​​Grid 布局默认按行排列,也可以按列排列(该属性和书写模式有关):

grid-auto-flow: column;

将物品放置在指定位置

​​用 grid-xxx-start or grid-xxx-end 指定物品横跨的列(行)数。

这里 xxxrow 或者 column ,下同。

比如横跨两列:

.item {
grid-column-end: span 2;
}

值默认为 auto ,即 1 ,或者直接指定列线号。或者用 grid-xxx 合并 startend ,用斜线 / 隔开两值。

这种跨越多行(列)的行为可能会导致空单元格的产生,可以设置容器的 grid-auto-flow 属性来让空单元格自动填充:

grid-auto-flow: row dense;

​​使用“基于行的定位”( line-based positioning )可以将物品直接覆盖在别的物品上。覆盖顺序会由加入顺序决定,或者用 z-index 属性来设置覆盖顺序,默认为 0 ,大数在上。

未明确网格

​​在一些情况下,比如:

  1. 设置了 grid-template-columns ,但没设置 grid-template-rows ,行轨道会自动调正自己的大小。

  2. 设置了一个超出范围的 grid-column-end ,网格容器会自动创建轨道来使之生效。

这些都被称为未明确网格( Implicit grid )。

在明确定义的网格中,可以用负数表示网格线,表示倒数,但是在未明确网格里是无法这么使用的。不过可以用 ​grid-auto-xxx 设置未明确轨道的大小。

网格线及区域的命名

​​给网格线命名(后面可以直接用这些值):

.container {
display: grid;
grid-template-columns:
[main-start aside-start] 1fr
[aside-end content-start] 2fr
[content-end main-end];
}

给区域命名​(在容器的子元素):

header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
footer { grid-area: footer; }

当所有要用的区域都命名后,可以应用在区域模板里:

.container {
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-areas:
"header header header header"
"sidebar content content content"
"sidebar footer footer footer";
}

使用区域模板应当:

  • 必须使用 任意数量 . 符号来表示空白;

  • 使用重复的名来横跨轨道;

  • 横跨的形状必须是完整矩形。

用 grid-template 简写

​​​​grid-template 可以整合 grid-template-areas grid-template-xxx 的属性值:

grid-template: 100px 1fr / 50px 1fr;
grid-template:
"a a a" 40px
"b c c" 40px
"b c c" 40px / 1fr 1fr 1fr;
grid-template: 
[header-top] "a a a" [header-bottom]
[main-top] "b b b" 1fr [main-bottom]
/ auto 1fr auto;

更多例子可以看 grid-template

对齐方式

​​flexbox 的对齐、空白分配属性都可以在 grid 中用:

  • justify-content & align-content

  • justify-self & align-self

  • justify-items & align-items


参考

Grid,Learn CSS - web.dev

网格布局 - MDN

grid - MDN

A Complete Guide to Grid,Chris House - css-tricks