Skip to content
大纲

网格布局

网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以将网格元素放置在与这些行和列相关的位置上。

核心概念

  • 网格容器:用于实现网格布局的元素
  • 网格元素:网格容器的所有直系子元素
  • 网格线:用来划分网格轨道的平行线,包括行网格线和列网格线,其编号顺序同文本方向
  • 网格轨道:相邻的两条平行的网格线之间的空间,包括行轨道和列轨道
  • 网格单元:相邻的列网格线和相邻的行网格线交叉形成的区域,网格单元是网格容器中最小的单位
  • 网格区域:网格单元向行或列方向扩展一个或多个单元形成的矩形区域
  • 网格间距:网格单元之间横向和纵向的间距,不包括网格单元与网格容器边缘之间的间距
  • 隐式网格:如果非固定宽高的网格容器无法容纳额外的网格元素,将按照一定规则创建隐式网格行轨道或列轨道,同时改变该方向上网格容器的尺寸
  • 嵌套网格:网格元素作为网格容器称为嵌套网格,嵌套网格与父级无关且无隐式网格

描述轨道

下面使用 <track> 表示一个轨道,使用 <track-list> 表示一组轨道


<track> 的描述格式为 [lineName-start] <track-size> [lineName-end] ,其中:

  • [lineName] 为网格线命名,可以使用多个命名,如 [line1-end line2-start]
  • [lineName-start][lineName-end] 为可选的,如果使用,则需要含在方括号内
  • [lineName-start][lineName-end] 使用 '-start' 和 '-end' 作为后缀时将自动生成同名(去掉后缀)的 grid-area
  • <track-size>表示轨道的尺寸,可以:
    • 使用传统尺寸单位,如 px
    • 使用 % 单位: 相对于网格容器的百分比,如果网格容器的尺寸依赖于网格轨道,则该值视为 auto
    • 使用 fr 单位
      • 该单位将对容器当前方向上的剩余空间进行占比分配,若无剩余空间则依据网格元素内容的最大尺寸
      • 当轨道 fr 值之和小于 1 时,各轨道依据 fr 值占据剩余空间的对应的百分比而非依据各轨道自身占比
    • 使用 auto 单位,该单位将对容器依据网格元素尺寸进行自适应,如果网格元素内容超出,将依据其他网格元素内容剩余空间进行调整(该行为与fr不一致)
    • 使用 min-content:
    • 使用 max-content:
    • 使用 fit-content([<length> | <percentage>]):
    • 使用 minmax(min, max) 函数: 该函数将限制轨道的最大最小尺寸

<track-list> 的描述格式为

  • 对每一个轨道进行单独描述,如 <track1> <track2> ...
  • 使用 repeat(<interger>|auto-fill, <track>) 可以对重复的轨道进行简写,使用整数指定重复次数或使用 auto-fill 关键字让容器自动计算最大可填充列数(轨道尺寸不能指定为 fr)
  • 使用上述两种方式混合使用

例子:

css
.wrapper {
  display: grid;
  grid-template-columns:
    [nav-start] 200px [nav-end main-start] repeat(3, minmax(300px, auto))
    [main-end rest-start] 1fr [rest-end];
}

网格容器

  • 创建容器:通过给元素指定样式 display: grid;display: inline-grid; 创建一个网格容器。
  • 定义结构:通过 grid-template-rowsgrid-template-columns 定义行与列轨道
  • 定义布局:通过 grid-template-areas 定义命名网格区域布局
  • 隐式网格:通过 grid-auto-flow 指定隐式网格创建方向,通过 grid-auto-rowsgrid-auto-columns 指定隐式网格轨道创建规则
  • 定义间距:通过 grid-gap-rowsgrid-gap-columns 定义横向和列向的网格元素间距

grid-template-rows

  • 说明
    • 定义网格容器行轨道
  • 格式
    • grid-template-rows: <track-list>;
  • 取值
    • none: 表示不明确的指定栅格,所有的行和其尺寸由 grid-auto-rows 属性隐式指定
    • <track-list>: 见 '描述轨道'

grid-template-columns

  • 说明
    • 定义网格容器列轨道
  • 格式
    • grid-template-columns: <track-list>
  • 取值
    • none: 表示不明确的指定栅格,所有的列和其尺寸由 grid-auto-columns 属性隐式指定
    • <track-list>: 见 '描述轨道'

grid-template-areas

  • 说明
    • 定义网格区域的结构
  • 示例
css
.container {
  display: grid;
  grid-template-rows: repeat(3, 1fr);
  grid-template-columns: repeat(3, 1fr);
  grid-template-areas:
    "hd hd hd"
    "bd bd bd"
    ".. ft ..";
}
  • 取值
    • none
    • grid areas 结构
  • 格式
    • 如示例所示,'hd'、'bd'、'ft' 为网格区域名称,'..' 表示空白区域
    • 每一行使用一组网格区域名称放在引号中进行描述,行与行之间使用空格或换行分隔
    • 跨越相邻行或列的网格区域名称描述一个网格区块
    • 网格区块需要为矩形
  • 默认
    • none

grid-template

  • 说明
    • 该属性为 grid-template-columnsgrid-template-rowsgrid-template-areas 的复合属性
    • 该属性通常用于进行创建简单网格,对于复杂的网格应当将其拆分为单一属性以提升可读性
  • 取值
    • none: 相当于 grid-template-columns: none; grid-template-rows: none; grid-template-areas: none;
    • 见格式
  • 默认
    • none
  • 格式
    • 格式 ①:<grid-template-rows> / <grid-template-columns>
    • 格式 ②:<grid-template-areas> <grid-template-rows> / <grid-template-column>
  • 注意
    • 格式 ① 在 '/' 左右添加 [lineName] 时在 vscode 中会报错(猜测为 bug 或部分插件限制),提示应当将其进行拆分为单一属性
    • 格式 ② 可以在 <grid-template-areas> <grid-template-rows> 前后添加网格线命名,在 vscode 中会报同样的错误,应当将其拆分为单一属性
    • 猜测上述 vscode 中的报错为编译器认为属性值过于复杂会提升理解难度,这种写法应当禁止
  • 示例
css
.container {
  display: grid;
  grid-template: 100px repeat(2, 200px) 100px / 100px 1fr;
  grid-template:      /* 指定了网格区域名称的情况 */
    "hd hd" 100px
    "nv bd" 100px
    "nv bd" 100px
    "ft ft" 100px
    / 100px 1fr;
}

grid-auto-flow

  • 说明
    • 指定网格元素在自动布局中的排列方向
  • 语法
    • [row | column] | [dense]
  • 取值
    • row: 自动布局算法按照逐行填充来排列元素
    • column: 自动布局算法按照逐列填充来排列元素
    • dense: 使用稠密堆积算法,容器试图使用小尺寸元素填充网格中之前留下的空白,可能导致元素次序被打乱
    • row dense: 自动布局为列方向,使用稠密堆积算法
    • column dense: 自动布局为行方向,使用稠密堆积算法
  • 默认
    • row

grid-auto-columns

  • 说明
    • 指定隐式创建的列轨道尺寸
  • 取值
    • <track-size>
    • <track-size-list>
  • 注意
    • 不支持 repeat 模式描述的轨道列表

grid-auto-rows

  • 说明
    • 指定隐式创建的行轨道尺寸
  • 取值
    • <track-size>
    • <track-size-list>
  • 注意
    • 不支持 repeat 模式描述的轨道列表

grid-row-gap

  • 说明
    • 指定网格行轨道之间的行间隔间距
    • 指定轨道间隔间距可能会使内容超出网格容器
  • 取值
    • <length>: 固定的行轨道间隔间距
    • <percentage>: 间距尺寸依据网格容器高度,需要先指定网格容器的 height 值,否则不生效
  • 注意
    • 此为行轨道之间的间隔间距,不包括行轨道与网格容器之间的间隔
    • 若存在 fr 计算的轨道,轨道间距不在剩余空间内
    • 取值为百分比时需指定容器高度,该行为与 grid-auto-flow 无关

grid-column-gap

  • 说明
    • 指定网格列轨道之间的列间隔间距
    • 指定轨道间隔间距可能会使内容超出网格容器
  • 取值
    • <length>: 固定列轨道间距间距
    • <percentage>: 间距尺寸依据网格容器宽度
  • 注意
    • 此为列轨道之间的间隔间距,不包括列轨道与网格容器之间的间隔
    • 若存在 fr 计算的轨道,轨道间距不在剩余空间内

grid-gap

  • 说明
    • 该属性为 grid-column-gapgrid-row-gap 的复合属性
  • 格式
    • grid-gap: <gap>: 该简写 column-gap 值同 row-gap
    • grid-gap: <row-gap> <column-gap>
  • 取值
    • <length>: 固定的轨道间隔间距
    • <percentage>: 间距尺寸依据网格容器尺寸,列方向的网格间距需要先指定网格容器的 height 值,否则不生效
  • 注意
    • 此为轨道之间的间隔间距,不包括轨道与网格容器之间的间隔
    • 若存在 fr 计算的轨道,轨道间距不在剩余空间内
    • <row=gap> 取值为百分比时需指定容器高度,该行为与 grid-auto-flow 无关

align-items

  • 说明
    • 指定网格元素在列轴上的对齐方式
  • 取值
    • start: 块方向开始位置对齐
    • center: 块方向居中对齐
    • end: 块方向末尾位置对齐
    • stretch: 拉伸
  • 注意
    • 具有指定宽高的网格元素,默认行为为 start
    • 没有指定宽高的网格元素,默认行为为 stretch

justify-items

  • 说明
    • 指定网格元素在行轴上的对齐方式
  • 取值
    • start: 行方向开始位置对齐
    • center: 行方向居中对齐
    • end: 行方向末尾位置对齐
    • stretch: 拉伸
  • 注意
    • 具有指定宽高的网格元素,默认行为为 start
    • 没有指定宽高的网格元素,默认行为为 stretch

align-content

  • 说明
    • 当总网格区域尺寸小于网格容器时,可以设置网格轨道的对齐方式
    • 这里要求总网格区域块方向尺寸小于网格容器高度
  • 取值
    • start
    • center
    • end
    • stretch: 拉伸
    • space-around: 均匀分布,网格元素间距相等,网格元素与网格容器间距为网格元素间距的一半
    • space-between: 两端对齐,网格元素间距相等
    • space-evenly: 等距分布,网格元素间距,网格元素与网格容器间距相同
  • 注意
    • stretch 时,若网格轨道为固定值则失效

justify-content

  • 说明
    • 当总网格区域尺寸小于网格容器时,可以设置网格轨道的对齐方式
    • 这里要求总网格区域行方向尺寸小于网格容器宽度
  • 取值
    • start
    • center
    • end
    • stretch: 拉伸
    • space-around: 均匀分布,网格元素间距相等,网格元素与网格容器间距为网格元素间距的一半
    • space-between: 两端对齐,网格元素间距相等
    • space-evenly: 等距分布,网格元素间距,网格元素与网格容器间距相同
  • 注意
    • stretch 时,若网格轨道为固定值则失效

网格元素

网格元素定位可以通过以下方式进行描述

  • 基于网格线的描述
    • 使用网格线编号(注意:网格线编号是从 1 开始计算的)
    • 使用网格线名称
  • 基于命名网格区域的描述
    • 使用网格区域名称

grid-column-start && grid-row-start

  • 说明
    • 指定网格元素起始位置
    • 未指定网格元素结束位置时默认延当前方向跨越 1 个轨道
  • 取值
    • auto
    • <line-name>: 起始位置为指定的命名列网格线
    • <integer>: 起始位置为指定编号的列网格线,若为负数则从行方向尾部开始计算
    • span <integer>: 指定跨越的轨道数,需要与 grid-column-endgrid-row-end 结合使用
    • span <line-name>: 指定起始网格线,需指定 grid-column-endgrid-row-end 才生效

grid-column-end && grid-row-end

  • 说明
    • 指定网格元素的结束位置
    • 未指定网格元素开始位置时默认逆当前方向跨越 1 个轨道
  • 取值
    • auto
    • <line-name>
    • span <integer>
    • span <line-name>

grid-column && grid-row

  • 说明
    • grid-columngrid-column-startgrid-column-end 的复合属性
    • grid-rowgrid-row-startgrid-row-end 的复合属性
  • 格式
    • grid-column: <column-start> / <column-end>
    • grid-row: <row-start> / <row-end>
    • grid-column: <linename>: 相当于 grid-column: <linename-start> / <linename-end> 的简写
    • grid-row: <linename>: 相当于 grid-row: <linename-start> / <linename-end> 的简写

grid-area

  • 说明
    • 该属性为 grid-row-startgrid-column-startgrid-row-endgrid-column-end 的简写
    • 也可以指定为一个命名网格区域的名称

align-self

  • 说明
    • 作用于网格元素
    • 效果同 align-items
    • 设置该属性将优先于 align-items 的作用效果

justify-self

  • 说明
    • 作用于网格元素
    • 效果同 justify-items
    • 设置该属性将优先于 justify-items 的作用效果

示例

html
<div layout="grid" class="container">
  <div class="header"></div>
  <div class="nav"></div>
  <div class="main"></div>
  <div class="footer"></div>
</div>
css
* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

[layout="grid"] {
  display: grid;
  border: 1px solid #000;
}

[layout="grid"] > div {
  border: 1px dashed #aaa;
}

@media screen and (min-width: 720px) {
  .container {
    grid-template-columns: 240px minmax(480px, 1fr);
    grid-template-rows: 100px auto 80px;
    grid-template-areas: "header header" "nav main" "nav footer";
  }
}

@media screen and (max-width: 720px) {
  .container {
    grid-template-columns: minmax(640px, 1fr);
    grid-template-rows: 100px 80px auto 80px;
    grid-template-areas: "header" "nav" "main" "footer";
  }
}

.header {
  grid-area: header;
  background: red;
}

.nav {
  grid-area: nav;
  background: green;
}

.main {
  grid-area: main;
  background: blue;
  height: 600px;
}

.footer {
  grid-area: footer;
  background: orange;
}