CSS Grid 布局是 CSS 中最强大的布局系统。与 flexbox 的一维布局系统不同,CSS Grid 布局是一个二维布局系统,也就意味着它可以同时处理列和行。通过将 CSS 规则应用于 父元素 (成为 Grid Container 网格容器)和其 子元素(成为 Grid Items 网格项),你就可以轻松使用 Grid(网格) 布局。
有两个主要因素激发了我创建本指南的灵感。第一个是 Rachel Andrew 出色的书籍 为 CSS Grid 布局做好准备 。这本书对 Grid 布局做了全面,清晰的介绍 ,也是本指南的基础。我强烈建议你购买并阅读。另一个灵感来自 Chris Coyier 的 Flexbox 布局完整指南,这也是我学习 flexbox 首选的资源。这篇文章是帮助了很多人,这点从 Google “flexbox” 排名第一就可以看出来。你会发现那篇文章和我的文章有很多相似之处,为什么不跟随最好的文章呢?
截至2017年3月,许多浏览器都提供了对 CSS Grid 的原生支持,而且无需加浏览器前缀:Chrome(包括 Android ),Firefox,Edge,Safari(包括iOS)和 Opera 。 另一方面,Internet Explorer 10和11支持它,但是是一个过时的语法实现。 现在是时候使用 Grid 布局网页了!
这个浏览器支持 CSS Grid 的数据,来自Caniuse ,你可以查看更多的细节。 数字表示支持以上功能的浏览器版本号。
Chrome | Opera | Firefox | IE | Edga | Safari |
---|---|---|---|---|---|
57 | 44 | 52 | 11*(旧语法) | 16 | 10.1 |
iOS Safari | Opera Mobile | Opera Mini | Android | Android Chrome | Android Firefox |
---|---|---|---|---|---|
10.3 | 46 | No | 67 | 70 | 63 |
除了微软之外,浏览器厂商似乎还没有对 Grid(网格) 搞自己的一套实现(比如加前缀),直到规范完全成熟。这是一件好事,因为这意味着我们不必担心学习多个语法。
在生产中使用 Grid 只是时间问题。 但现在是学习的时候了。
应用 【display: grid 】的元素。这是所有 网格项(grid item)的直接父级元素。在这个例子中,【container 】就是 网格容器(Grid Container)。
HTML代码:
HTML代码:
值:
CSS代码:
.container {
display: grid | inline-grid;
}
注意:通过嵌套元素(也称为子网格,即 subgrid )向下传递网格参数的能力已移至 CSS Grid 规范的 Level 2 版本。这里有 一个快速解释。
值:
CSS代码:
.container {
grid-template-columns: ... | ...;
grid-template-rows: ... | ...;
}
示例:
当你在 网格轨道(Grid Track) 值之间留出空格时,网格线会自动分配正数和负数名称:
CSS代码:
.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}
但是你可以明确的指定网格线(Grid Line)名称,例如 值。请注意网格线名称的括号语法:
CSS 代码:
.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];
}
请注意,一条网格线(Grid Line)可以有多个名称。例如,这里的第二条 行网格线(row grid lines) 将有两个名字:row1-end 和 row2-start :
CSS代码:
.container {
grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}
如果你的定义包含多个重复值,则可以使用 repeat() 表示法来简化定义:
CSS 代码:
.container {
grid-template-columns: repeat(3, 20px [col-start]);
}
上面的代码等价于:
CSS 代码:
.container {
grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start];
}
如果多行共享相同的名称,则可以通过其网格线名称和计数来引用它们。
CSS 代码:
.item {
grid-column-start: col-start 2;
}
fr 单元允许你用等分网格容器剩余可用空间来设置 网格轨道(Grid Track) 的大小 。例如,下面的代码会将每个网格项设置为网格容器宽度的三分之一:
CSS 代码:
.container {
grid-template-columns: 1fr 1fr 1fr;
}
剩余可用空间是除去所有非灵活网格项 之后 计算得到的。在这个例子中,可用空间总量减去 50px 后,再给 fr 单元的值 3 等分:
CSS 代码:
.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}
值:
CSS 代码:
.container {
grid-template-areas:
" | . | none | ..."
"...";
}
示例:
CSS 代码:
.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";
}
上面的代码将创建一个 4 列宽 3 行高的网格。整个顶行将由 header 区域组成。中间一排将由两个 main 区域,一个是空单元格,一个 sidebar 区域组成。最后一行全是 footer 区域组成。
你可以使用任意数量的相邻的 点. 来声明单个空单元格。 只要这些点.之间没有空隙隔开,他们就代表一个单独的单元格。
注意你 不能 用这个语法来命名网格线,只是命名 网格区域 。当你使用这种语法时,区域两端的网格线实际上会自动命名。如果你的网格区域的名字是 foo,该区域的起始行网格线 和 起始列网格线 的名称将为 foo-start,而最后一条行网格线 和 最后一条列网格线 的名称将为 foo-end。这意味着某些网格线可能有多个名字,如上例中最左边的网格线,它将有三个名称:header-start,main-start 和 footer-start 。
值:
CSS 代码:
.container {
grid-template: none | / ;
}
这个属性也接受一个更复杂但非常方便的语法来指定三个上诉属性。这里有一个例子:
CSS 代码:
.container {
grid-template:
[row1-start] "header header header" 25px [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
等价于:
CSS 代码:
.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 lines)的大小。你可以把它想象为设置列/行之间间距的宽度。
值:
CSS 代码:
.container {
grid-column-gap: ;
grid-row-gap: ;
}
示例:
CSS 代码:
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-column-gap: 10px;
grid-row-gap: 15px;
}
注意:这两个属性将删除 【grid-】 前缀,就是将 【grid-column-gap】 和 【grid-row-gap】重命名为 【column-gap】 和 【row-gap】。 Chrome 68+,Safari 11.2 Release 50+ 和Opera 54+ 已经支持无前缀的属性。
值:
CSS 代码:
.container {
grid-gap: ;
}
示例:
CSS 代码:
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-gap: 15px 10px;
}
如果【grid-row-gap】没有定义,那么就会被设置为等同于 【grid-column-gap】 的值。例如下面的代码是等价的:
CSS 代码:
.container{
/* 设置 grid-column-gap 和 grid-row-gap */
grid-column-gap: 10px;
grid-row-gap: 10px;
/* 等价于 */
grid-gap: 10px 10px;
/* 等价于 */
grid-gap: 10px;
}
注意:这个属性将删除 【grid- 】前缀,就是将 【grid-gap】 重命名为 【gap】。 Chrome 68+,Safari 11.2 Release 50+ 和Opera 54+ 已经支持无前缀的属性。
沿着 inline(行)轴线对齐网格项(grid items)(相反的属性是 【align-items】 沿着 block(列)轴线对齐)。此值适用于容器内的所有网格项。
值:
CSS 代码:
.container {
justify-items: start | end | center | stretch;
}
示例:
CSS 代码:
.container {
justify-items: start;
}
.container{
justify-items: end;
}
.container{
justify-items: center;
}
.container{
justify-items: stretch;
}
这些行为也可以通过每个单独网格项(grid items) 的 【justify-self】 属性设置。
start
:将网格项对齐到其单元格的顶部起始边缘(顶部对齐)end
:将网格项对齐到其单元格的底部结束边缘(底部对齐)center
:将网格项对齐到其单元格的垂直中间位置(垂直居中对齐)stretch
:填满单元格的高度(默认值)CSS 代码:
.container {
align-items: start | end | center | stretch;
}
示例:
CSS 代码:
.container {
align-items: start;
}
.container {
align-items: end;
}
.container {
align-items: center;
}
.container {
align-items: center;
}
这些行为也可以通过每个单独网格项(grid items) 的 align-self
属性设置。
值:
:第一个值设置 align-items
属性,第二个值设置justify-items
属性。如果省略第二个值,则将第一个值同时分配给这两个属性。除 Edge 之外的所有主要浏览器都支持 place-items
简写属性。
有关更多详细信息,请参阅align-items
和 justify-items
。
值:
start
:将网格对齐到 网格容器(grid container) 的左侧起始边缘(左侧对齐)end
:将网格对齐到 网格容器的右侧结束边缘(右侧对齐)center
:将网格对齐到 网格容器 的水平中间位置(水平居中对齐)stretch
:调整 网格项(grid items) 的宽度,允许该网格填充满整个 网格容器 的宽度space-around
:在每个网格项之间放置一个均匀的空间,左右两端放置一半的空间space-between
:在每个网格项之间放置一个均匀的空间,左右两端没有空间space-evenly
:在每个网格项目之间放置一个均匀的空间,左右两端放置一个均匀的空间CSS 代码:
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
示例:
CSS 代码:
.container {
justify-content: start;
}
.container {
justify-content: end;
}
.container {
justify-content: center;
}
.container {
justify-content: stretch;
}
.container {
justify-content: space-around;
}
.container {
justify-content: space-between;
}
.container {
justify-content: space-evenly;
}
值:
start
:将网格对齐到 网格容器(grid container) 的顶部起始边缘(顶部对齐)end
:将网格对齐到 网格容器 的底部结束边缘(底部对齐)center
:将网格对齐到 网格容器 的垂直中间位置(垂直居中对齐)stretch
:调整 网格项(grid items)的高度,允许该网格填充满整个 网格容器 的高度space-around
:在每个网格项之间放置一个均匀的空间,上下两端放置一半的空间space-between
:在每个网格项之间放置一个均匀的空间,上下两端没有空间space-evenly
:在每个网格项目之间放置一个均匀的空间,上下两端放置一个均匀的空间CSS 代码:
.container {
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
}
示例:
CSS 代码:
.container {
align-content: start;
}
.container {
align-content: end;
}
.container {
align-content: center;
}
.container {
align-content: stretch;
}
.container {
align-content: space-around;
}
.container {
align-content: space-between;
}
.container {
align-content: space-evenly;
}
值:
:第一个值设置 align-content
属性,第二个值设置justify-content
属性。如果省略第二个值,则将第一个值同时分配给这两个属性。除 Edge 之外的所有主要浏览器都支持 place-content
简写属性。
有关更多详细信息,请参阅align-content
和 justify-content
。
值:
:可以是长度值,百分比,或者等份网格容器中可用空间的分数(使用 fr 单位)CSS 代码:
.container {
grid-auto-columns: ...;
grid-auto-rows: ...;
}
为了说明如何创建隐式网格轨道,请考虑一下以下的代码:
CSS 代码:
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px
}
这将生成了一个 2×2 的网格。
但现在想象一下,你使用 grid-column 和 grid-row 来定位你的网格项,像这样:
CSS 代码:
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
我们告诉 .item-b
从第 5 条列网格线开始到第 6 条列网格线结束,但我们从来没有定义过 第5 或 第6 列网格线。
因为我们引用的网格线不存在,所以创建宽度为 0 的隐式网格轨道以填补空缺。我们可以使用 grid-auto-columns
和 grid-auto-rows
来指定这些隐式轨道的大小:
CSS 代码:
.container {
grid-auto-columns: 60px;
}
如果你有一些没有明确放置在网格上的网格项(grid items),自动放置算法 会自动放置这些网格项。该属性控制自动布局算法如何工作。
值:
row
:告诉自动布局算法依次填充每行,根据需要添加新行 (默认)column
:告诉自动布局算法依次填入每列,根据需要添加新列dense
:告诉自动布局算法在稍后出现较小的网格项时,尝试填充网格中较早的空缺CSS 代码:
.container {
grid-auto-flow: row | column | row dense | column dense
}
请注意,dense
只会更改网格项的可视顺序,并可能导致它们出现乱序,这对可访问性不利。
示例:
考虑以下 HTML :
HTML 代码:
item-a
item-b
item-c
item-d
item-e
你定义一个有 5 列和 2 行的网格,并将 grid-auto-flow 设置为 row(也就是默认值):
CSS 代码:
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: row;
}
将网格项放在网格上时,只能为其中的两个指定位置:
CSS 代码:
.item-a {
grid-column: 1;
grid-row: 1 / 3;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
}
因为我们把 grid-auto-flow
设成了 row
,所以我们的网格看起来会是这样。注意 我们没有进行定位的网格项(item-b,item-c,item-d
)会这样排列在可用的行中:
相反地,如果我们把 grid-auto-flow
设成了 column
,那么 item-b,item-c,item-d
会沿着列向下排列:
CSS 代码:
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: column;
}
在一个声明中设置所有以下属性的简写: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, 和 grid-auto-flow 。(注意:您只能在单个网格声明中指定显式或隐式网格属性)。
值:
none
:将所有子属性设置为其初始值。
:与grid-template
简写的工作方式相同。 / [ auto-flow && dense? ] ?
:将grid-template-rows
设置为指定的值。 如果 auto-flow
关键字位于斜杠的右侧,则会将grid-auto-flow
设置为 column
。 如果另外指定了 dense
关键字,则自动放置算法使用 “dense
” 算法。如果省略 grid-auto-columns
,则将其设置为 auto
。[ auto-flow && dense? ]? /
:将 grid-template-columns
设置为指定值。 如果 auto-flow
关键字位于斜杠的左侧,则会将grid-auto-flow
设置为 row
。 如果另外指定了dense
关键字,则自动放置算法使用 “dense
” 打包算法。 如果省略 grid-auto-rows
,则将其设置为 auto
。例子:
以下两个代码块是等效的:
CSS 代码:
.container {
grid: 100px 300px / 3fr 1fr;
}
CSS 代码:
.container {
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
}
以下两个代码块是等效的:
CSS 代码:
.container {
grid: auto-flow / 200px 1fr;
}
CSS 代码:
.container {
grid-auto-flow: row;
grid-template-columns: 200px 1fr;
}
以下两个代码块是等效的:
CSS 代码:
.container {
grid: auto-flow dense 100px / 1fr 2fr;
}
CSS 代码:
.container {
grid-auto-flow: row dense;
grid-auto-rows: 100px;
grid-template-columns: 1fr 2fr;
}
以下两个代码块是等效的:
CSS 代码:
.container {
grid: 100px 300px / auto-flow 200px;
}
CSS 代码:
.container {
grid-template-rows: 100px 300px;
grid-auto-flow: column;
grid-auto-columns: 200px;
}
它也接受一个更复杂但相当方便的语法来一次设置所有内容。您可以指定 grid-template-areas,grid-template-rows和grid-template-columns
,并所有其他的子属性都被设置为它们的初始值。这么做可以在它们网格区域内相应地指定网格线名字和网格轨道的大小。用最简单的例子来描述:
CSS 代码:
.container {
grid: [row1-start] "header header header" 1fr [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
等价于:
CSS 代码:
.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;
}
Grid Items)
属性注意:float,display: inline-block,display: table-cell,vertical-align 和 column-*
属性对网格项无效。
grid-column-start / grid-column-end / grid-row-start / grid-row-end
通过引用特定网格线(grid lines) 来确定 网格项(grid item) 在网格内的位置。 grid-column-start / grid-row-start
是网格项开始的网格线,grid-column-end / grid-row-end
是网格项结束的网格线。
值:
:可以是一个数字引用一个编号的网格线,或者一个名字来引用一个命名的网格线span
:该网格项将跨越所提供的网格轨道数量span
:该网格项将跨越到它与提供的名称位置auto
:表示自动放置,自动跨度,默认会扩展一个网格轨道的宽度或者高度CSS 代码:
.item {
grid-column-start: | | span | span | auto
grid-column-end: | | span | span | auto
grid-row-start: | | span | span | auto
grid-row-end: | | span | span | auto
}
示例:
CSS 代码:
.item-a {
grid-column-start: 2;
grid-column-end: five;
grid-row-start: row1-start
grid-row-end: 3;
}
CSS 代码:
.item-b {
grid-column-start: 1;
grid-column-end: span col4-start;
grid-row-start: 2
grid-row-end: span 2
}
如果没有声明指定 grid-column-end / grid-row-end,默认情况下,该网格项将占据 1 个轨道。
项目可以相互重叠。您可以使用 z-index 来控制它们的重叠顺序。
分别为 grid-column-start + grid-column-end
和 grid-row-start + grid-row-end
的简写形式。
值:
/
:每个网格项都接受所有相同的值,作为普通书写的版本,包括跨度CSS 代码:
.item {
grid-column: / | / span ;
grid-row: / | / span ;
}
示例:
CSS 代码:
.item-c {
grid-column: 3 / span 2;
grid-row: third-line / 4;
}
如果没有声明分隔线结束位置,则该网格项默认占据 1 个网格轨道。
为网格项提供一个名称,以便可以 被使用网格容器 grid-template-areas
属性创建的模板进行引用。 另外,这个属性可以用作grid-row-start + grid-column-start + grid-row-end + grid-column-end
的简写。
值:
:
你所选的名称 / / /
:数字或分隔线名称CSS 代码:
.item {
grid-area: | / / / ;
}
示例:
作为为网格项分配名称的一种方法:
CSS 代码:
.item-d {
grid-area: header
}
作为grid-row-start + grid-column-start + grid-row-end + grid-column-end 属性
的简写形式
CSS 代码:
.item-d {
grid-area: 1 / col4-start / last-line / 6
}
沿着 inline
(行)轴线对齐网格项( 相反的属性是 align-self ,沿着 block(列)轴线对齐)。此值适用于单个网格项内的内容。
值:
start
:将网格项对齐到其单元格的左侧起始边缘(左侧对齐)end
:将网格项对齐到其单元格的右侧结束边缘(右侧对齐)center
:将网格项对齐到其单元格的水平中间位置(水平居中对齐)stretch
:填满单元格的宽度(默认值)CSS 代码:
.item {
justify-self: start | end | center | stretch;
}
示例:
CSS 代码:
.item-a {
justify-self: start;
}
CSS 代码:
.item-a {
justify-self: end;
}
CSS 代码:
.item-a {
justify-self: center;
}
CSS 代码:
.item-a {
justify-self: stretch;
}
要为网格中的所有网格项设置 行轴线(row axis) 线上对齐方式,也可以在 网格容器 上设置 justify-items 属性。
沿着 block(列)轴线对齐网格项(grid items)( 相反的属性是 justify-self ,沿着 inline(行)轴线对齐)。此值适用于单个网格项内的内容。
值:
start
:将网格项对齐到其单元格的顶部起始边缘(顶部对齐)end
:将网格项对齐到其单元格的底部结束边缘(底部对齐)center
:将网格项对齐到其单元格的垂直中间位置(垂直居中对齐)stretch
:填满单元格的高度(默认值)CSS 代码:
.item{
align-self: start | end | center | stretch;
}
示例:
CSS 代码:
.item-a {
align-self: start;
}
CSS 代码:
.item-a {
align-self: end;
}
CSS 代码:
.item-a {
align-self: center;
}
CSS 代码:
.item-a {
align-self: stretch;
}
要为网格中的所有网格项设置 列轴线(column axis) 上的对齐方式,也可以在 网格容器 上设置 align-items 属性。
place-self 是设置 align-self 和 justify-self 的简写形式。
值:
auto
– 布局模式的 “默认” 对齐方式。
:第一个值设置 align-self 属性,第二个值设置 justify-self 属性。如果省略第二个值,则将第一个值同时分配给这两个属性。CSS 代码:
.item-a {
place-self: center;
}
CSS 代码:
.item-a {
place-self: center stretch;
}
除 Edge 之外的所有主要浏览器都支持 place-self 简写属性。
根据 CSS Grid 布局模块 Level 1 规范,有 5 个可应用动画的网格属性:
grid-gap, grid-row-gap,grid-column-gap
作为长度,百分比或 calc。grid-template-columns,grid-template-rows
作为长度,百分比或 calc 的简单列表,只要列表中长度、百分比或calc组件的值不同即可。截至今天(2018年5月7日),在测试的几个浏览器中仅实现 (grid-)gap,(grid-)row-gap,(grid-)column-gap 的动画。
浏览器支持可设置动画的网格属性:
浏览器 | (grid-)gap, (grid-)row-gap, (grid-)column-gap | grid-template-columns | (grid-template-rows |
---|---|---|---|
Firefox 55+, Firefox 53+ Mobile | ✅ | ❌ | ❌ |
Safari 11.0.2 | ❌ | ❌ | ❌ |
Chrome 66+ | ✅ | ❌ | ❌ |
Chrome for Android 66+, Opera Mini 33+ | ✅ | ❌ | ❌ |
Edge 16+ | ✅ | ❌ | ❌ |
https://codepen.io/feiwen8772/embed/QJedqL?height=479&theme-id=0&slug-hash=QJedqL&default-tab=result&animations=run&editable=&embed-version=2&user=feiwen8772&name=cp_embed_1