效果更好
Grid
网格布局(
Grid
)是最强大的CSS
布局方案。 将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。Flex
布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid
布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid
布局远比Flex
布局强大。
.box{
display:grid;
}
行元素使用flex
布局;
.box{
display:inline-grid;
}
<aside> 💡 注意,设为网格布局以后,容器子元素(项目)的float
、display: inline-block
、display: table-cell
、vertical-align
和column-*
等设置都将失效。
</aside>
浏览器支持情况
桌面(Desktop) 浏览器 | |||||
---|---|---|---|---|---|
Chrome | Opera | Firefox | IE | Edge | Safari |
57 | 44 | 52 | 11*(旧语法) | 16 | 10.1 |
手机(Mobile) / 平板(Tablet)浏览器 | |||||
iOS Safari | Opera Mobile | Opera Mini | Android | Android Chrome | Android Firefox |
10.3 | 46 | No | 67 | 70 | 63 |
基本概念
容器
(Grid Container
)和项目
采用网格布局的区域,称为"
容器
"(container
)。
容器
内部采用网格定位的子元素,称为"项目
"(item
)。
<div>
<div><p>1</p></div>
<div><p>2</p></div>
<div><p>3</p></div>
</div>
- 最外层的<div>元素就是
容器
,内层的三个<div>元素就是项目
<aside> 💡 注意:项目
只能是容器
的顶层子元素,不包含项目的子元素,比如上面代码的<p>元素就不是项目
。Grid
布局只对项目
生效。
</aside>
-
行和列(
grid row
)- 容器里面的水平区域称为"
行
",垂直区域称为"列
"(column
)。
- 容器里面的水平区域称为"
-
单元格(
grid cell
)-
行和列的交叉区域,称为"
单元格
"。例:正常情况下,n行和m列会产生n x m个
单元格
。比如,3行3列会产生9个单元格
。
-
-
网格线(
grid line
)-
划分网格的线,称为"
网格线
"。水平网格线
划分出行,垂直网格线
划分出列。 -
n
行有n + 1
根水平网格线,m
列有m + 1
根垂直网格线,比如三行就有四根水平网格线
-
-
网格轨道(
Grid Track
)-
两条相邻
网格线
之间的空间。你可以把它们想象成网格的列
或行
。下图是第二条和第三条行网格线
之间的网格轨道
(Grid Track
)。
-
-
网格区域(
Grid Area
)-
4条
网格线
包围的总空间。一个网格区域
(Grid Area
)可以由任意数量的网格单元格
(Grid Cell
)组成。 -
下图是
行网格线
1和3,以及列网格线
1和3之间的网格区域
。
-
-
单位
fr
:(fraction
的缩写,意为"片段
”)剩余空间分配数。用于在一系列长度值中分配剩余空间,如果多个已指定了多个部分,则剩下的空间根据各自的数字按比例分配。gr
:网格数(w3c暂未收录)
容器属性(17)
-
grid-template-columns & grid-template-rows
grid-template-columns
属性定义每一列的列宽;grid-template-rows
属性定义每一行的行高。.container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; }
-
使用百分比
.container { display: grid; grid-template-columns: 33.33% 33.33% 33.33%; grid-template-rows: 33.33% 33.33% 33.33%; }
-
repeat()
.container { display: grid; grid-template-columns: repeat(3, 33.33%); grid-template-rows: repeat(3, 33.33%); }
.container { display: grid; /* grid-template-columns: 100px 20px 80px 100px 20px 80px; */ grid-template-columns: repeat(2, 100px 20px 80px); grid-template-rows: repeat(3, 33.33%); }
-
auto-fill
- 单元格的大小是固定的,但是容器的大小不确定。每一行(或每一列)容纳尽可能多的单元格,可以使用
auto-fill
关键字表示自动填充。
.container { display: grid; grid-template-columns: repeat(auto-fill, 100px); }
<aside> 💡 表示每列宽度
100px
,然后自动填充,直到容器不能放置更多的列。</aside>
- 单元格的大小是固定的,但是容器的大小不确定。每一行(或每一列)容纳尽可能多的单元格,可以使用
-
fr
.container { display: grid; grid-template-columns: 1fr 1fr; /* grid-template-columns: 50% 50%; */ }
.container { display: grid; grid-template-columns: 150px 1fr 2fr; /* 第一列150px 剩余空间分为3份, 第二列 1份 第三列 2份 */ }
-
minmax()
minmax()
函数产生一个长度范围,表示长度就在这个范围之中。接受两个参数,分别为最小值和最大值。
.container { display: grid; grid-template-columns: 1fr 1fr minmax(100px, 1fr) /* 总共分为3份 第一列 1份 第二列 1份 第三列 1份(最小为100px,最大为1fr) */ }
-
auto
auto
关键字表示由浏览器自己决定长度
.container { display: grid; grid-template-columns: 100px auto 100px; /* 第一列 100px 第二列 总共减去200px 第三列 100px */ }
.container { display: grid; grid-template-columns: auto 0.25fr .25fr .25fr; }
<aside> 💡 后边三列 容器宽度 - “宽auto”字符宽度) * 0.25, 第一列 宽度为 字节宽度加上 0.25fr;
</aside>
-
网格线的名称
.container { display: grid; grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4]; grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4]; }
<aside> 💡 网格布局允许同一根线有多个名字,比如
[fifth-line row-5]
</aside>
-
实例
- 两栏式布局只需要一行代码
.container { display: grid; grid-template-columns: 70% 30%; }
- 十二网格布局
.container { display: grid; grid-template-columns: repeat(12, 1fr); }
-
-
grid-template-areas
网格布局允许指定"区域"(
area
),一个区域由单个或多个单元格组成。grid-template-areas
属性用于定义区域。.container { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-template-areas: 'a b c' 'd e f' 'g h i'; }
<aside> 💡 划分出9个单元格,然后将其定名为
a
到i
的九个区域,分别对应这九个单元格</aside>
-
多个
单元格
合并成一个区域
grid-template-areas: 'a a a' 'b b b' 'c c c';
-
某些区域不需要利用,则使用"点"(
.
)表示grid-template-areas: 'a . c' 'd . f' 'g . i';
-
需要指定对应
class
为指定区域
;.container { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr ; grid-template-areas: "header header header" "sidebar content content" "sidebar content content" "footer footer footer" } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .content { grid-area: content; } .footer{ grid-area: footer; }
<div class="container"> <div class="header">头部</div> <div class="sidebar">侧边栏</div> <div class="content">内容</div> <div class="footer">底部</div> </div>
<aside> 💡 注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start
,终止网格线自动命名为区域名-end
。 比如,区域名为header
,则起始位置的水平网格线和垂直网格线叫做header-start
,终止位置的水平网格线和垂直网格线叫做header-end
。</aside>
<aside> 💡 网格区域一定要形成规整的矩形区域,什么L形,凹的或凸的形状都是不支持的,会认为是无效的属性值。
</aside>
-
-
grid-template(
grid-template-rows
、**grid-template-columns**
、**grid-template-areas**
简写)grid-template
是grid-template-rows
,grid-template-columns
和grid-template-areas
属性的缩写。.container { grid-template: none; } .container { grid-template: <grid-template-rows> / <grid-template-columns>; }
.container { display: grid; grid-template: "header header header" 1fr "sidebar content content" 1fr "sidebar content content" 1fr "footer footer footer" 1fr / 1fr 1fr 1fr; }
<aside> 💡 由于
grid-template
不会重置一些隐式的grid属性(如grid-auto-columns
、grid-auto-rows
、grid-auto-flow
), 因此,大多数时候,还是推荐使grid
代替grid-template
</aside>
-
column-gap(grid-column-gap) & row-gap(grid-row-gap)
grid-column-gap
:设置列与列的间隔(列间距)grid-row-gap
:设置行与行的间隔(行间距).container { grid-row-gap: 20px; grid-column-gap: 20px; }
<aside> 💡 根据最新标准,上面三个属性名的
grid-
前缀已经删除,grid-column-gap
和grid-row-gap
写成column-gap
和row-gap
,grid-gap
写成gap
。</aside>
-
gap(grid-gap)(
column-gap
、row-gap
简写)grid-gap
:grid-column-gap
和grid-row-gap
的合并简写形式grid-gap: <grid-row-gap> <grid-column-gap>;
.container { grid-gap: 20px 20px; }
<aside> 💡
grid-gap
省略了第二个值,浏览器认为第二个值等于第一个值。</aside>
-
justify-items
justify-items
指定了网格元素的水平呈现方式,是水平拉伸显示,还是左中右对齐,单元格
的内容
.container { justify-items: stretch | start | end | center; }
stretch
(默认值):表现为水平填充。更正:默认值是legacy
。start
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线左侧对齐显示(假设文档流方向没有变)。end
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线右侧对齐显示(假设文档流方向没有变)。center
:表现为网格水平尺寸收缩为内容大小,同时在当前网格区域内部水平居中对齐显示(假设文档流方向没有变)。
-
align-items
align-items
指定了网格元素的垂直呈现方式,是垂直拉伸显示,还是上中下对齐;单元格
的内容
.container { align-items: stretch | start | end | center; }
stretch
(默认值):拉伸。表现为垂直填充。start
:表现为网格垂直尺寸收缩为内容大小,同时沿着上网格线对齐显示。end
:表现为网格垂直尺寸收缩为内容大小,同时沿着下网格线对齐显示。center
:表现为网格垂直尺寸收缩为内容大小,同时在当前网格区域内部垂直居中对齐显示。
-
place-items(
align-items
、justify-items
简写)place-items
可以让align-items
和justify-items
属性写在单个声明中;.container { place-items: <align-items> <justify-items>; }
.container { place-items: start end; }
<aside> 💡 如果省略第二个值,则浏览器认为与第一个值相等。
</aside>
-
justify-content
justify-content
指定了网格元素的水平分布方式;单元格
justify-content: stretch | start | end | center | space-between | space-around | space-evenly;
.container { display: grid; width: 300px; grid-template: 100px 100px/100px 100px; /* grid-template: auto auto/auto auto; */ }
stretch
(默认值):拉伸,宽度填满grid容器,拉伸效果需要网格目标尺寸设为auto时候才有效,如果定死了宽度,则无法拉伸。start
:逻辑CSS属性值,与文档流方向相关。默认表现为左对齐。end
:逻辑CSS属性值,与文档流方向相关。默认表现为右对齐。center
:表现为居中对齐。space-between
:表现为两端对齐。space-around
:视觉上边缘两侧的空白只有中间空白宽度一半。space-evenly
:间隙匀称、平等的分;
-
align-content
align-content
则是指明垂直方向每一行grid元素的分布方式。单元格
align-content: stretch | start | end | center | space-between | space-around | space-evenly;
stretch
(默认值):每一行grid子元素都等比例拉伸。start
:逻辑CSS属性值,与文档流方向相关。默认表现为顶部堆砌。end
:逻辑CSS属性值,与文档流方向相关。默认表现为底部堆放。center
:表现为整体垂直居中对齐。space-between
:表现为上下两行两端对齐。剩下每一行元素等分剩余空间。space-around
:每一行元素上下都享有独立不重叠的空白空间。space-evenly
:每一行元素都完全上下等分。
-
place-content(
align-content
、justify-content
简写)place-content
可以让align-content
和justify-content
属性写在一个CSS声明中,也就是俗称的缩写.container { place-content: <align-content> <justify-content>; }
-
grid-auto-columns & grid-auto-rows
指定任何自动生成的网格轨道(也称为
隐式网格轨道
)的大小。 当网格项目多于网格中的单元格
或网格项目
放置在显式网格之外时,将创建隐式轨道
。grid-auto-columns
属性和grid-auto-rows
属性用来设置,浏览器自动创建的多余网格的列宽和行高。 如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。.container { display: grid; width: 150px; grid-template-columns: 60px 60px; grid-template-rows: 30px 90px; grid-auto-columns: 60px; } .item-a { grid-column: 1 / 2; grid-row: 2 / 3; } .item-b { /* 容器水平只有2个格子,但这里设定的是第3个,隐式网格创建 */ grid-column: 3 / 4; grid-row: 2 / 3; background-color: rgba(255,255,0, .5); }
-
grid-auto-flow
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"
先行后列
",即先填满第一行,再开始放入第二行;.container { grid-auto-flow: row | column | row dense | column dense }
row
(默认值):没有指定位置的网格依次水平排列优先。column
:没有指定位置的网格依次垂直排列优先。row dense
:表示"先行后列
",并且尽可能紧密填满,尽量不出现空格。column dense
:表示"先列后行
",并且尽量填满空格。
-
grid(
grid-template-rows
、**grid-template-columns**
、**grid-template-areas
、grid-auto-columns
、grid-auto-rows
、grid-auto-flow
简写)**
项目属性(10)
-
grid-column-start & grid-column-end
grid-column-start
属性:左边框所在的垂直网格线grid-column-end
属性:右边框所在的垂直网格线.item { grid-column-start: <number> | <name> | span <number> | span <name> | auto grid-column-end: <number> | <name> | span <number> | span <name> | auto }
-
grid-row-start & grid-row-end
grid-row-start
属性:上边框所在的水平网格线grid-row-end
属性:下边框所在的水平网格线.item { grid-row-start: <number> | <name> | span <number> | span <name> | auto grid-row-end: <number> | <name> | span <number> | span <name> | auto }
<number>
起止与第几条网格线。<name>
自定义的网格线的名称。span <number>
表示当前网格会自动跨越指定的网格数量。span <name>
表示当前网格会自动扩展,直到命中指定的网格线名称。auto
全自动,包括定位,跨度等。
.container { grid-template-columns: [第一根纵线] 80px [纵线2] auto [纵线3] 100px [最后的结束线]; grid-template-rows: [第一行开始] 25% [第一行结束] 100px [行3] auto [行末]; } .item-a { grid-column-start: 2; grid-column-end: 纵线3; grid-row-start: 第一行开始; grid-row-end: 3; }
<div class="container"> <div class="item-a"></div> </div>
grid-column-start:2
表示.item-a
网格左侧起始于<number>
为2
的线;grid-column-end:纵线3
表示.item-a
网格右侧结束于<name>
为纵线3
的线;grid-row-start:第一行开始
表示.item-a
网格上方开始于<name>
为第一行开始
的线;grid-row-end:3
表示.item-a
网格下方结束于<number>
为3
的线。
.item-b { grid-column-start: 2; grid-column-end: span 纵线3; grid-row-start: 第一行开始; grid-row-end: span 3; }
<div class="container"> <div class="item-b"></div> </div>
grid-row-end:span 3
表示当前网格需要覆盖3个格子;
<aside> 💡 对于命名的网格线,有
span
和没有span
没有区别(包括多个同名网格线)。</aside>
-
grid-column(
grid-column-start
、grid-column-end
简写) & grid-row(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>; }
- 管道分隔符
|
表示“或者” <start-line>
就是grid-*-start
属性值,<end-line>
就是grid-*-end
属性值
.item-b { grid-column: 2 / span 纵线3; grid-row: 第一行开始 / span 3; }
<=>
.item-b { grid-column-start: 2; grid-column-end: span 纵线3; grid-row-start: 第一行开始; grid-row-end: span 3; }
- 管道分隔符
-
grid-area(
grid-row-start
、grid-column-start
、grid-row-end
、grid-column-end
|grid-template-areas
简写)grid-area
表示当前网格所占用的区域grid-area
其实是grid-row-start
,grid-column-start
,grid-row-end
以及grid-column-end
属性的缩写, 以及额外支持grid-template-areas
设置的网格名称而已.item { grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>; }
<name>
区域名称。由grid-template-areas
属性创建。<row-start>
/<column-start>
/<row-end>
/<column-end>
占据网格区域的纵横起始位置。
.container { grid-template: 1fr 1fr 1fr/1fr 1fr 1fr 1fr; } .item-c { grid-area: 1 / 2 / 3 / 4; }
-
justify-self
justify-self
属性设置单元格中内容的水平位置(左中右).item { justify-self: start | end | center | stretch; }
stretch
(默认值):拉伸。表现为水平填充start
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线左侧对齐显示。end
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线右侧对齐显示。center
:表现为网格水平尺寸收缩为内容大小,同时在当前网格区域内部水平居中对齐显示。
-
align-self
align-self
属性设置单元格中内容的垂直位置(上中下).item { align-self: start | end | center | stretch; }
stretch
(默认值):拉伸。表现为垂直填充。start
:表现为网格垂直尺寸收缩为内容大小,同时沿着上网格线对齐显示。end
:表现为网格垂直尺寸收缩为内容大小,同时沿着下网格线对齐显示。center
:表现为网格垂直尺寸收缩为内容大小,同时在当前网格区域内部垂直居中对齐显示。
-
place-self(
align-self
、justify-self
简写)place-items
可以让align-self
和justify-self
属性写在单个声明中.item { place-self: <align-self> <justify-self>? }