Grid 网格布局

Grid 用于二维布局,是 CSS 第一个真正意义上的布局系统。

.container {
  /*  
    grid: 把容器当作 block 再按 grid 布局其项目。
    inline-grid: 把容器当作 inline 再按 grid 布局其项目。
  */
  display: grid | inline-grid;
}
1
2
3
4
5
6
7
<div class="container">
  <div class="item item-1"> </div>
  <div class="item item-2"> </div>
  <div class="item item-3"> </div>
</div>
1
2
3
4
5

术语

grid line

line

网格线 line 的编号从 1 开始,和书写模式有关(rtl 时最右边的是 1)。

grid track

track

track 指两条 line 之间的空间。row track 就是 row line 间,column track 就是 column line 间的空间。

grid cell

cell

单元格 cell 是最小单元,是行和列的交叉区域。

grid area

area

area 是一组 cell 在一起。

grid gap

gap

gap 是 track 间的空隙。

容器属性

grid-template-columns,grid-template-rows

grid-template-columns:
grid-template-rows:
text
text
a loooooooong text
你们中大多数人都熟悉程序员的美德,有三种:那就是懒惰、急躁和傲慢。
5

定义网格的列、行。其值表示 track 的大小,分隔各值用的空格相当于 line 。包含:

  • track 大小 – 可以为长度、百分比、fr 等
  • 网格线命名 – 自动生成或用户指定的名字

网格线命名

网格线将从 1 开始被自动赋值(或从最后一条线开始从 -1 开始赋值)。 line

但也可以为网格线指定明确的名字:

.container {
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}
1
2
3
4

line

网格线可以同时有多个名字:

.container {
  grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}
1
2
3

重名的网格线可以通过其名字和序号引用到:

.item {
  grid-column-start: col-start 2;
}
1
2
3

grid-template-areas

依据 grid-area 所定义的区域名来定义整个网格的区域。可选值有三种:

  • 与 grid-area 所对应的区域名
  • . 表示空的单元格
  • none 表示区域未定义

示例:

header
main
sidebar
footer
.item-a {
  grid-area: header;
}
.item-b {
  grid-area: main;
}
.item-c {
  grid-area: sidebar;
}
.item-d {
  grid-area: footer;
}

.container {
  display: grid;
  height: 200px;
  grid-template-columns: 50px 1fr 50px 50px;
  grid-template-rows: 40px auto 20px;
  grid-template-areas: 
    "header header header header"
    "main main . sidebar"
    "footer footer footer footer";
}

















 
 
 
 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="container">
  <div class="item-a">header</div>
  <div class="item-b">main</div>
  <div class="item-c">sidebar</div>
  <div class="item-d">footer</div>
</div>
1
2
3
4
5
6

区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为 区域名-start,终止网格线自动命名为 区域名-end。正因此,某些网格线可能有多个名字,如上例最左侧网格线可用的命名为:header-start, main-start 及 footer-start

grid-template

grid-template-rows grid-template-columns grid-template-areas 的缩写形式。

综合使用示例:

.container {
  grid-template:
    [row1-start] "header header header" 25px [row1-end]
    [row2-start] "footer footer footer" 25px [row2-end]
    / auto 50px auto;
}
/* 等价于:*/
.container {
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;
  grid-template-areas: 
    "header header header" 
    "footer footer footer";
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

通常最好使用 grid 代替 grid-template

column-gap,row-gap

column-gap:   row-gap:
 
 
 
 
 
 

定义网格线的大小,可理解为行列间隙的宽度。

注:grid-column-gap grid-row-gap 为废弃属性。

gap

row-gap column-gap 的缩写形式。

注:grid-gap 为废弃属性。

justify-items

justify-items:
stretch
stretch
stretch
stretch
stretch
stretch

设置容器内所有 row 轴上的对齐方式。

align-items

align-items:
stretch
stretch
stretch
stretch
stretch
stretch

设置容器内所有 column 轴上的对齐方式。

可以使用修饰符关键字:

  • safe 安全对齐方式会避免数据丢失的出现,将溢出转移到一边
  • unsafe 不安全的对齐方式导致的对齐结果可能会发生数据丢失
align-items: safe end
1

place-items

align-items justify-items 的缩写形式。

justify-content

justify-content:
1
2
3
4
5
6

用于网格整体内容的尺寸小于网格容器时,用来对齐整个网格在 row 轴上的内容。

align-content

align-content:
1
2
3
4
5
6

用于网格整体内容的尺寸小于网格容器时,用来对齐整个网格在 column 轴上的内容。

place-content

align-content justify-content 的缩写形式。

grid-auto-columns,grid-auto-rows

grid-auto-columns:
grid-auto-rows:
A
B

用来给自增的 track 设置尺寸。如上例中创建了两个区域:

grid

.container {
  grid-template-columns: 60px 60px;
  grid-template-rows: 90px 90px;
}
.item-a {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}
.item-b {
  grid-column: 5 / 6;
  grid-row: 2 / 3;
}









 


1
2
3
4
5
6
7
8
9
10
11
12

区域 B 设置为 grid-column: 5 / 6,但事实上并未定义这些网格线。由于引用了不存在的网格线,将会创建宽度为 0 的 track 来填补这些空隙。而 grid-auto-columns 正是用来定义这些 track 的宽度的。row 方向上同理。

grid-auto-flow

当网格中存在未明确指定位置的项目元素时,该属性用来指定其 自动摆放算法 采用的方式。可选值:

  • row – 指示自动摆放算法按行的顺序按需增加新项目元素 (默认)
  • column – 指示自动摆放算法按列的顺序按需增加新项目元素
  • dense - 指示自动摆放算法尽量优先使用更小的项目元素摆放

例如,只指定区域 a、e 时:

.item-a {
  grid-column: 1;
  grid-row: 1 / 3;
}
.item-e {
  grid-column: 5;
  grid-row: 1 / 3;
}
1
2
3
4
5
6
7
8
<section class="container">
  <div class="item-a">item-a</div>
  <div class="item-b">item-b</div>
  <div class="item-c">item-c</div>
  <div class="item-d">item-d</div>
  <div class="item-e">item-e</div>
</section>
1
2
3
4
5
6
7

如果使用 row 则效果为:

grid

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: row;
}




 

1
2
3
4
5
6

如果使用 column 则效果为:

grid

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: column;
}




 

1
2
3
4
5
6

grid

以下属性的简写形式:

  • grid-template-rows
  • grid-template-columns
  • grid-template-areas
  • grid-auto-rows
  • grid-auto-columns
  • grid-auto-flow
.container {
  grid: 100px 300px / 3fr 1fr;
}

.container {
  grid-template-rows: 100px 300px;
  grid-template-columns: 3fr 1fr;
}
1
2
3
4
5
6
7
8
.container {
  grid: auto-flow / 200px 1fr;
}

.container {
  grid-auto-flow: row;
  grid-template-columns: 200px 1fr;
}
1
2
3
4
5
6
7
8
.container {
  grid: auto-flow dense 100px / 1fr 2fr;
}

.container {
  grid-auto-flow: row dense;
  grid-auto-rows: 100px;
  grid-template-columns: 1fr 2fr;
}
1
2
3
4
5
6
7
8
9
.container {
  grid: 100px 300px / auto-flow 200px;
}

.container {
  grid-template-rows: 100px 300px;
  grid-auto-flow: column;
  grid-auto-columns: 200px;
}
1
2
3
4
5
6
7
8
9
.container {
  grid: [row1-start] "header header header" 1fr [row1-end]
        [row2-start] "footer footer footer" 25px [row2-end]
        / auto 50px auto;
}

.container {
  grid-template-areas: 
    "header header header"
    "footer footer footer";
  grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;    
}
1
2
3
4
5
6
7
8
9
10
11
12
13

项目元素属性

注意 设为 grid 布局以后,容器项目的 float、display: inline-block、display: table-cell、vertical-align 和 column-* 等设置都将失效。

grid-column-start,grid-column-end,grid-row-start,grid-row-end

依据网格线来定义网格元素在网格中的位置。可选值为:

  • {grid line} – 网格线的数字序号或名字
  • span {number} – 合并指定 number 数量的网格 track
  • span {name} – 合并至指定的 name 网格线处
  • auto – 浏览器自动计算
.item {
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start;
  grid-row-end: 3;
}
1
2
3
4
5
6

grid

.item {
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2;
  grid-row-end: span 2;
}
1
2
3
4
5
6

grid

如果未指定 end 值,项目只会穿过 1 个 track 。

grid-column,grid-row

grid-columngrid-column-start grid-column-end 的简写形式, grid-rowgrid-row-start grid-row-end 的简写形式。

.item {
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}
1
2
3
4

grid-area

共有两个用法,一是配合 grid-template-areas 使用,用来指定区域名:

.item {
  grid-area: header;
}
1
2
3

另外,还可以作为 grid-row-start grid-column-start grid-row-end grid-column-end 的简写形式:

.item {
  grid-area: 1 / col4-start / last-line / 6;
}
1
2
3

justify-self

justify-self: justify-items:
stretch
stretch
stretch
stretch
stretch
stretch

其效果同 justify-items ,但只针对指定的项目生效。

align-self

align-self: align-items:
stretch
stretch
stretch
stretch
stretch
stretch

其效果同 align-items ,但只针对指定的项目生效。

place-self

align-self justify-self 的简写形式:

特殊单位和函数

fr

fr 表示剩余空间中的一部分,如下例表示 2 列分别占 25%、75% 。

grid-template-columns: 1fr 3fr;
1

其与百分比的区别在于:如果存在 padding(如下例中的 padding:50px),% 将会导致宽度不再是 100%;而 fr 不会造成该问题。

1fr
3fr
25%
75%

单位 fr 计算的是去除所有非弹性项目后的空间,如:

.container {
  grid-template-columns: 1fr 50px 1fr 1fr;
}
1
2
3

会用总宽度减去 50px 后再将剩余空间三等分给 1、3、4 列。显然,单位 fr 在与其它单位联合使用时更为友好:

grid-template-columns: 50px min-content 1fr;
1

min-content

依据其内容的最小尺寸显示:

The very long hotdog.
.container {
  display: grid;
  grid-template-columns: min-content 1fr 1fr;
  gap: 10px;
}


 


1
2
3
4
5
<div class="container">
  <div class="item">The very long hotdog.</div>
  <div class="item"></div>
  <div class="item"></div>
</div>

 



1
2
3
4
5

max-content

依据其内容的最大尺寸显示:

The very long hotdog.
.container {
  display: grid;
  grid-template-columns: max-content 1fr 1fr;
  gap: 10px;
}


 


1
2
3
4
5
<div class="container">
  <div class="item">The very long hotdog.</div>
  <div class="item"></div>
  <div class="item"></div>
</div>

 



1
2
3
4
5

fit-content

min-contentmax-content 之间调整可用空间:

The very long hotdog.
 
 
.container {
  display: grid;
  grid-template-columns: fit-content 1fr 1fr;
  gap: 10px;
}


 


1
2
3
4
5
<div class="container">
  <div class="item">The very long hotdog.</div>
  <div class="item"></div>
  <div class="item"></div>
</div>

 



1
2
3
4
5

PS: 当前 Chrome (97.0.4692.99) 不支持该关键字。

minmax()

container 的 width:   px
minmax(200px, 1fr)
3fr

即长度所允许的最小、最大值,因此它限定了一个长度范围。通常配合其它相对单位使用时非常方便。

repeat()

网格很多时,可简化重复的值。repeat() 接受两个参数:1)重复的次数; 2)所要重复的值。

grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
/* 简写为: */
grid-template-columns: repeat(8, 1fr);
1
2
3

有时单元格的大小是固定的,但是容器的大小不确定。如果希望一行(或列)容纳尽可能多的单元格,可以配合 auto-fill 关键字自动填充。

grid-template-columns: repeat(auto-fit, minmax(100px, 1fr))
1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Last Updated:
Contributors: ssbunny