Grid布局

106 阅读9分钟

CSS 网格布局(Grid Layout) 是CSS中最强大的布局系统。 这是一个二维系统,这意味着它可以同时处理列和行,不像 flexbox 那样主要是一维系统。 你可以通过将CSS规则应用于父元素(成为网格容器)和该元素的子元素(网格元素),来使用网格布局。

父容器

将父元素设置display:grid

  • grid - 生成一个块级(block-level)网格
  • inline-grid - 生成一个行级(inline-level)网格
  • subgrid - 如果你的 grid container 本身就是一个 grid item(即,嵌套网格),你可以使用这个属性来表示你想从它的父节点获取它的行/列的大小,而不是指定它自己的大小。
.container {
  display: grid | inline-grid | subgrid;
}

grid-template-columns / grid-template-rows

用于划分网格,对网格设置行列以及宽度

.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}

比如轨道值之间仅仅有空格时,网格线会被自动分配数字名称:

.container {
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

也可以给网格线命名:

.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];
}

需要注意的是,一个网格线可以有不止一个名字。例如,这里第2条网格线有两个名字:row1-end 和 row2-start:

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

如果定义中有重复,可以写成:

.container {
  grid-template-columns: repeat(3, 20px [col-start]) 5%;
}

等价于

.container {
  grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%;
}

单位fr

“fr”单位允许您将轨道大小设置为网格容器自由空间的一部分。

.container {
  grid-template-columns: 1fr 1fr 1fr;
}

将每个 grid item 为 grid container 宽度的三分之一。

自由空间是在排除所有不可伸缩的 grid item 之后计算得到的。 在下面的示例中,fr单位可用的自由空间总量不包括50px:

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

grid-template-areas

通过引用 grid-area属性指定的网格区域的名称来定义网格模板,也就是为子元素分配网格区域。

  • <grid-area-name> 使用 grid-area 属性设置的网格区域的名称
  • . 点号代表一个空网格单元
  • none 没有定义网格区域

需要给子元素命名:

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

然后为子元素分配网格:

.container {
  grid-template-columns: 50px 50px 50px 50px;
  grid-template-rows: auto;
  grid-template-areas: 
    "header header header header"
    "main main . sidebar"
    "footer footer footer footer";
}

这将创建一个四列宽三行高的网格。 整个第一行将由 header 区域组成。 中间一行将由两个 main 区域、一个空单元格和一个 sidebar 区域组成。 最后一行是footer区域组成。

grid-template

在单个声明中定义 grid-template-rows、grid-template-columns、grid-template-areas 的简写。

  • none 将三个属性都设置为其初始值

  • subgrid 把 grid-template-rows 和 grid-template-columns 设置为 subgrid, 并且 grid-template-areas 设置为初始值

  • grid-template-rows / <grid-template-columns - 把 grid-template-columns 和 grid-template-rows 设置为指定值, 与此同时, 设置 grid-template-areas 为 none

.container {
  grid-template: none | subgrid | <grid-template-rows> / <grid-template-columns>;
}

也可以使用更复杂的简写:

.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";
}

grid-column-gap / grid-row-gap

设置网格之间的间隙

  • line-size 一个长度值
.container {
  grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
}

比如:

.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  grid-column-gap: 10px;
  grid-row-gap: 15px;
}

grid-gap

grid-row-gap 和 grid-column-gap 的缩写

.container {
  grid-gap: <grid-row-gap> <grid-column-gap>;
}

justify-items

沿着行轴对齐网格内的内容(与之对应的是 align-items, 即沿着列轴对齐),该值适用于容器内的所有的 grid items。

  • start: 内容与网格区域的左端对齐
  • end: 内容与网格区域的右端对齐
  • center: 内容位于网格区域的中间位置
  • stretch: 内容宽度占据整个网格区域空间(这是默认值)
.container {
  justify-items: start | end | center | stretch;
}

justify-content

有时,网格的总大小可能小于其网格容器的大小。如果你的所有 grid items 都使用像px这样的非弹性单位来设置大小,则可能发生这种情况。此时,你可以设置网格容器内的网格的对齐方式。 此属性沿着行轴对齐网格(与之对应的是 align-content, 沿着列轴对齐)。

  • start - 网格与网格容器的左边对齐
  • end - 网格与网格容器的右边对齐
  • center - 网格与网格容器的中间对齐
  • stretch - 调整g rid item 的大小,让宽度填充整个网格容器
  • space-around - 在 grid item 之间设置均等宽度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
  • space-between - 在 grid item 之间设置均等宽度空白间隙,其外边缘无间隙
  • space-evenly - 在每个 grid item 之间设置均等宽度的空白间隙,包括外边缘
.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}

align-content

有时,网格的总大小可能小于其网格容器的大小。如果你的所有 grid items 都使用像px这样的非弹性单位来设置大小,则可能发生这种情况。此时,你可以设置网格容器内的网格的对齐方式。 此属性沿着列轴对齐网格(与之对应的是 justify-content, 即沿着行轴对齐)。

  • start - 网格与网格容器的顶部对齐
  • end - 网格与网格容器的底部对齐
  • center - 网格与网格容器的中间对齐
  • stretch - 调整 grid item 的大小,让高度填充整个网格容器
  • space-around - 在 grid item 之间设置均等宽度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
  • space-between - 在 grid item 之间设置均等宽度空白间隙,其外边缘无间隙
  • space-evenly - 在每个 grid item 之间设置均等宽度的空白间隙,包括外边缘
.container {
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}

grid-auto-columns / grid-auto-rows 指定自动生成的网格轨道(又名隐式网格轨道)的大小。

  • <track-size> - 可以是一个长度值,一个百分比值,或者一个自由空间的一部分(使用 fr 单位)
.container {
  grid-auto-columns: <track-size> ...;
  grid-auto-rows: <track-size> ...;
}

比如:

.item-a {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}

表示a从列线1到2,横线从2到3的范围内。

grid-auto-flow

如果你存在没有显示指明放置在网格上的 grid item,则自动放置算法会自动放置这些项目。

  • row - 告诉自动布局算法依次填充每行,根据需要添加新行
  • column - 告诉自动布局算法依次填充每列,根据需要添加新列
  • dense - 告诉自动布局算法,如果后面出现较小的 grid item,则尝试在网格中填充空洞
.container {
  grid-auto-flow: row | column | row dense | column dense
}

grid

在单个属性中设置所有以下属性的简写:grid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns和grid-auto-flow。 它同时也将 sets grid-column-gap 和 grid-row-gap 设置为它们的初始值,即使它们不能被此属性显示设置。

  • none - 将所有子属性设置为其初始值
  • <grid-template-rows> / <grid-template-columns> - 将 grid-template-rows 和 grid-template-columns 分别设置为指定值,将所有其他子属性设置为其初始值
  • <grid-auto-flow> [<grid-auto-rows> [ / <grid-auto-columns>] ] - 接受所有与grid-auto-flow,grid-auto-rows和grid-auto-columns相同的值。 如果省略grid-auto-columns,则将其设置为为grid-auto-rows指定的值。 如果两者都被省略,则它们被设置为它们的初始值
.container {
    grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}

孩子(Grid Items)的属性

grid-column-start / grid-column-end / grid-row-start /grid-row-end

使用特定的网格线确定 grid item 在网格内的位置。grid-column-start/grid-row-start 属性表示grid item的网格线的起始位置,grid-column-end/grid-row-end属性表示网格项的网格线的终止位置。

  • <line>: 可以是一个数字来指代相应编号的网格线,也可使用名称指代相应命名的网格线
  • span <number>: 网格项将跨越指定数量的网格轨道
  • span <name>: 网格项将跨越一些轨道,直到碰到指定命名的网格线
  • auto: 自动布局, 或者自动跨越, 或者跨越一个默认的轨道
.item {
  grid-column-start: <number> | <name> | span <number> | span <name> | auto
  grid-column-end: <number> | <name> | span <number> | span <name> | auto
  grid-row-start: <number> | <name> | span <number> | span <name> | auto
  grid-row-end: <number> | <name> | span <number> | span <name> | auto
}

比如:

.item-a {
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start
  grid-row-end: 3
}

grid-column / grid-row

grid-column-start + grid-column-end, 和 grid-row-start + grid-row-end 的简写形式。

.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}

grid-area

给 grid item 进行命名以便于使用 grid-template-areas 属性创建模板时来进行引用。另外也可以做为 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写形式。

  • <name> - 你的命名
  • <row-start> / <column-start> / <row-end> / <column-end> - 可以是数字,也可以是网格线的名字
.item {
  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}

justify-self

沿着行轴对齐grid item 里的内容(与之对应的是 align-self, 即沿列轴对齐)。 此属性对单个网格项内的内容生效。

  • start - 将内容对齐到网格区域的左端
  • end - 将内容对齐到网格区域的右端
  • center - 将内容对齐到网格区域的中间
  • stretch - 填充网格区域的宽度 (这是默认值)
.item-a {
  justify-self: start;
}

align-self

沿着列轴对齐grid item 里的内容(与之对应的是 justify-self, 即沿行轴对齐)。 此属性对单个网格项内的内容生效。

  • start - 将内容对齐到网格区域的顶部
  • end - 将内容对齐到网格区域的底部
  • center - 将内容对齐到网格区域的中间
  • stretch - 填充网格区域的高度 (这是默认值)
.item {
  align-self: start | end | center | stretch;
}

比如:

.item-a {
  align-self: start;
}