一、前言
网格是一组相交的水平线和垂直线,它定义了网格的列和行。我们可以将网格元素放置在与这些行和列相关的位置上。 CSS网格布局引入了二维网格布局系统,可用于布局页面主要的区域布局或小型组件。
二、网格容器
给<div>
这类块级元素设置 display:grid
或给<span>
这类内联元素设置 display:inline-grid
来创建一个网格容器。一旦我们这样做,这个元素的所有直系子元素将成为网格元素,Grid布局即创建。
在下面这个例子中,这有一个类名为 wrapper 的div 元素作为容器 ,它内部有五个子元素。
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
将div.wrapper 作为一个网格容器,它的所有直系子元素将成为网格元素。
.wrapper {
display: grid;
}
效果图:
在Grid布局中,所有相关CSS属性正好分为两拨,一拨作用在grid容器上,还有一拨作用在grid子项上。具体参见下表:
作用在grid容器上 | 作用在grid子项上 |
---|---|
三、作用在grid容器上的CSS属性
1. grid-template-columns
和grid-template-rows
grid-template-columns
和grid-template-rows
分别定义网格的列和行,一个网格轨道就是网格中任意两条线之间的空间。
语法:
.wrapper {
grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
<track-size>
:单元网格的尺寸。可以是长度值,百分比值,以及fr单位(网格容器中可用空间的一等份)。<line-name>
:网格线的名字,可以任意命名。
fr:是单词fraction的缩写,表示分数。
fr单位代表网格容器中可用空间的一等份。
repeat():用来重复部分或整个轨道列表
例如网格:它起始轨道为20像素,接着重复了6个1fr的轨道,最后再添加了一个20像素的轨道
.wrapper {
display: grid;
grid-template-columns: 20px repeat(6, 1fr) 20px;
}
又如网格 :有共计10个轨道,1个1fr轨道后面跟着1个2fr轨道,该模式重复5次
.wrapper {
display: grid;
grid-template-columns: repeat(5, 1fr 2fr);
}
minmax()函数
设置自动创建的行高或者列宽最小值和最大值
例:自动创建的行高将会是最小100像素,最大为auto
grid-auto-rows: minmax(100px, auto);
2. grid-template-areas
通过引用 grid-area 属性指定的 网格区域(Grid Area) 名称来定义网格模板。重复网格区域的名称导致内容跨越这些单元格。一个点号(.)代表一个空单元格。这个语法本身可视作网格的可视化结构。
语法:
.wrapper {
grid-template-areas:
"<grid-area-name> | . | none | ..."
"...";
}
<grid-area-name>
:由网格项的 grid-area 指定的网格区域名称.
(点号) :代表一个空的网格单元none
:不定义网格区域
例如:
html代码:
<div class="wrapper">
<div class="putao">葡萄种植区</div>
<div class="longxia">龙虾养殖区</div>
<div class="yangyu">鱼类养殖区</div>
<div class="xigua">西瓜种植区</div>
</div>
css代码:
/*grid容器*/
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
grid-template-areas:
"葡萄 葡萄 葡萄"
"龙虾 养鱼 养鱼"
"龙虾 养鱼 养鱼"
"西瓜 西瓜 西瓜";
}
/*grid子项*/
.putao { grid-area: 葡萄; }
.longxia { grid-area: 龙虾; }
.yangyu { grid-area: 养鱼; }
.xigua { grid-area: 西瓜; }
效果图:
3. grid-template
grid-template
是一个简写的CSS属性,用于定义 grid-template-rows
,grid-template-columns
和grid-template-areas
属性。
语法:
.wrapper {
grid-template: none / <string>+;
}
/*即:*/
.wrapper {
grid-template: none;
}
.wrapper {
grid-template: <grid-template-rows> / <grid-template-columns>;
}
none
:表示将3个CSS属性都设置为初始值。<string>+
:每一个给定的字符串会生成一行,一个字符串中用空格分隔的每一个单元(cell)会生成一列。多个同名的,跨越相邻行或列的单元称为网格区块(grid area)。非矩形的网格区块是无效的。
例如:css代码:
.wrapper {
grid-template-areas: "head head"
"nav main"
"nav foot";
grid-template-rows: 50px 1fr 30px;
grid-template-columns: 150px 1fr;
}
/*等同于*/
.wrapper {
grid-template: "head head" 50px
"nav main" 1fr
"nav foot" 30px
/ 150px 1fr;
}
效果图:
4. grid-column-gap(column-gap)和grid-row-gap(row-gap)
grid-column-gap
和grid-row-gap
属性用来定义网格中网格间隙的尺寸。
语法如下:
.wrapper {
grid-column-gap: <line-size>;
grid-row-gap: <line-size>;
}
<line-size>
:网格间的间隙尺寸。
5. grid-gap(gap)
grid-gap属性是grid-column-gap和grid-row-gap属性的缩写。语法如下:
.wrapper {
grid-gap: <grid-row-gap> <grid-column-gap>;
}
先横row后竖column
CSS Grid Layout 起初是用 grid-gap 属性来定义的,目前逐渐被 gap 替代。但是,为了兼容那些不支持 gap 属性的浏览器,你需要像上面的例子一样,使用带有前缀的属性。
6. justify-items
justify-items指定了网格元素的水平呈现方式,是水平拉伸显示,还是左中右对齐,语法如下:
.wrapper {
justify-items: stretch | start | end | center;
}
stretch
:默认值,拉伸。表现为水平填充。start
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线左侧对齐显示(假设文档流方向没有变)。end
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线右侧对齐显示(假设文档流方向没有变)。center
:表现为网格水平尺寸收缩为内容大小,同时在当前网格区域内部水平居中对齐显示(假设文档流方向没有变)。
7. align-items
align-items指定了网格元素的垂直呈现方式,是垂直拉伸显示,还是上中下对齐,语法如下:
.wrapper {
align-items: stretch | start | end | center;
}
其中(假设文档流方向为网页默认):
- stretch:默认值,拉伸。表现为垂直填充。
- start:表现为网格垂直尺寸收缩为内容大小,同时沿着上网格线对齐显示。
- end:表现为网格垂直尺寸收缩为内容大小,同时沿着下网格线对齐显示。
- center:表现为网格垂直尺寸收缩为内容大小,同时在当前网格区域内部垂直居中对齐显示。
8. place-items
place-items
是align-items
和justify-items
的缩写(如果有兼容性顾虑,建议还是分开书写)。语法如下:
.wrapper {
place-items: <align-items> / <justify-items>;
}
align-items在前,justify-items在后
9. justify-content
justify-content
指定了网格元素的水平分布方式。此属性仅在网格总宽度小于grid容器宽度时候有效果。例如,我们网格设定的都是固定的宽度值,结果还有剩余空间。例如:
.wrapper {
display: grid;
width: 300px;
grid-template: 100px 100px/100px 100px;
}
此时,水平和垂直方向都有100px的剩余,justify-content属性此时就有用武之地了。
语法如下:
justify-content: stretch | start | end | center | space-between | space-around | space-evenly;
其中:
stretch
:默认值。拉伸,宽度填满grid容器,拉伸效果需要网格目标尺寸设为auto时候才有效,如果定死了宽度,则无法拉伸。start
:默认值。逻辑CSS属性值,与文档流方向相关。默认表现为左对齐。end
:逻辑CSS属性值,与文档流方向相关。默认表现为右对齐。center
:表现为居中对齐。-
space-between
:表现为两端对齐。between是中间的意思,意思是多余的空白间距只在元素中间区域分配。使用抽象图形示意如下:
-
space-around
:around是环绕的意思,意思是每个flex子项两侧都环绕互不干扰的等宽的空白间距,最终视觉上边缘两侧的空白只有中间空白宽度一半。使用抽象图形示意如下: space-evenly
:evenly是匀称、平等的意思。也就是视觉上,每个flex子项两侧空白间距完全相等。使用抽象图形示意如下:
10. align-content
align-content
是justify-content
相似且对立的属性,justify-content
指明水平方向grid子项的分布方式,而align-content
则是指明垂直方向每一行grid元素的分布方式。
语法如下:
align-content: stretch | start | end | center | space-between | space-around | space-evenly;
stretch
:默认值。每一行flex子元素都等比例拉伸。例如,如果共两行flex子元素,则每一行拉伸高度是50%。start
:逻辑CSS属性值,与文档流方向相关。默认表现为顶部堆砌。end
:逻辑CSS属性值,与文档流方向相关。默认表现为底部堆放。center
:表现为整体垂直居中对齐。space-between
:表现为上下两行两端对齐。剩下每一行元素等分剩余空间。space-around
:每一行元素上下都享有独立不重叠的空白空间。space-evenly
:每一行元素都完全上下等分。
11. place-content
place-content
是align-content
和justify-content
的缩写(如果有兼容性顾虑,建议还是分开书写)。语法如下:
.wrapper {
place-items: <align-content> / <justify-content>;
}
这里顺序是align-content
在前,justify-content
在后。
如果第二个值不存在,则第一个值用于两者,前提是它是两者的有效值。如果它对一个或另一个无效,则整个值将无效。
12. grid-auto-columns和grid-auto-rows
指定任何自动生成的网格轨道(也称为隐式网格轨道)的大小。 当网格项目多于网格中的单元格或网格项目放置在显式网格之外时,将创建隐式轨道。
语法如下:
.wrapper {
grid-auto-columns: <track-size> ...;
grid-auto-rows: <track-size> ...;
}
<track-size>
:网格中轨道的尺寸。可以是长度值,百分比值,以及fr单位(网格剩余空间比例单位)。
例:用 grid-auto-rows 属性来确保在隐式网格中创建的轨道是200像素高。
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
<style>
.wrapper {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 200px;
}
</style>
效果图:
13. grid-auto-flow
grid-auto-flow
属性控制没有明确指定位置的grid子项的放置方式。比方说定义了一个5*2的10格子,共有5个元素,其中2个元素指定了放在哪个格子里,还有3个则自生自灭排列。此时,这3个元素如何排列就是由grid-auto-flow
属性控制的。
语法如下:
.wrapper {
grid-auto-flow: row | column | row dense | column dense
}
row
:默认值。没有指定位置的网格依次水平排列优先,在必要时增加新行。column
:没有指定位置的网格依次垂直排列优先,在必要时增加新列。dense
:dense这个英文是稠密的意思。如果有设置,则表示自动排列启用“密集”打包算法。如果稍后出现的网格比较小,则尝试看看前面有没有合适的地方放置,使网格尽可能稠密紧凑。此属性值仅仅改变视觉顺序,会导致DOM属性和实际呈现顺序不符合,这对于可访问性是不友好的,建议谨慎使用。
14. grid
是下面所有这些CSS属性的缩写集合,grid-template-rows,grid-template-columns,grid-template-areas,grid-auto-rows,grid-auto-columns和grid-auto-flow。
语法如下:
-
grid: none
none表示设置所有的子属性为初始值。 grid: <grid-template>
和grid-template用法一致。例如这样:.wrapper { grid: 100px 300px / 3fr 1fr; } /*等同于下面:*/ .wrapper { grid-template-rows: 100px 300px; grid-template-columns: 3fr 1fr; }
grid: <grid-template-rows> / [ auto-flow && dense? ] <grid-auto-columns>?
问号?表示0或1,可有可无的意思。也就是dense关键字和grid-auto-columns
值都可以省略。
具体说明:
-
auto-flow && dense?其实就是grid-auto-flow属性的值,等同于row或column或row dense或column dense。
但这里row和column这两个关键字却使用了auto-flow这一个关键字代替了。那岂不有问题:什么时候解析成row,什么时候解析成column呢?
原来,是根据auto-flow关键字是在斜杠的左侧还是右侧决定的。如果auto-flow关键字在斜杠左侧,则解析为row,如果是在右侧,则解析为column。这里的语法是在斜杠的右侧,因此,会将grid-auto-flow解析为column。
-
<grid-auto-columns>
后面有个问号?,因此是可以省略的,如果省略,则将grid-auto-columns
解析为auto。
我们通过几个案例学习这里的语法:
.wrapper {
grid: repeat(2, 80px) / auto-flow 100px;
}
上面CSS代码省略了dense关键字,启用了<grid-auto-columns>
,因此,等同于下面CSS:
.wrapper {
grid-template-rows: repeat(2, 80px)
grid-auto-flow: column;
grid-auto-columns: 100px;
}
记住,在Grid布局中,斜杠前面都是rows相关属性,斜杠后面都是columns相关属性(下同)。
效果图:
grid: [ auto-flow && dense? ] <grid-auto-rows>? / <grid-template-columns>
此语法和上面一个语法类似,只是这个斜杠前面是隐式网格,后面是显示。在这里,由于auto-flow在斜杠左侧,因此解析为row。所以:.wrapper { grid: auto-flow dense 100px / 1fr 2fr; } /*就等同于下面CSS:*/ .wrapper { grid-auto-flow: row dense; grid-auto-rows: 100px; grid-template-columns: 1fr 2fr; }
四、作用在grid子项上的CSS属性
1. grid-column-start, grid-column-end, grid-row-start和grid-row-end
表示grid子项所占据的区域的起始和终止位置,包括水平方向和垂直方向。
语法如下:
.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
}
语法中的管道分隔符|表示“或者”的意思,因此上面实际上就一个属性值,具体来讲:
<number>
:起止与第几条网格线。<name>
:自定义的网格线的名称。span <number>
:表示当前网格会自动跨越指定的网格数量。span <name>
:表示当前网格会自动扩展,直到命中指定的网格线名称。auto
:全自动,包括定位,跨度等。
例:
<div class="wrapper">
<div class="box1">One</div>
<div class="box2">Two</div>
<div class="box3">Three</div>
<div class="box4">Four</div>
<div class="box5">Five</div>
</div>
<style>
.wrapper {
display: grid;
grid-template-columns: [第一根纵线] 80px [纵线2] auto [纵线3] 100px [最后的结束线];
grid-template-rows: [第一行开始] 25% [第一行结束] 100px [行3] auto [行末];
}
.box1 {
grid-column-start: 2;
grid-column-end: 纵线3;
grid-row-start: 第一行开始;
grid-row-end: 3;
}
.box2 {
grid-column-start: 1;
grid-row-start: 3;
grid-row-end: 4;
}
</style>
效果图:
2. grid-column和grid-row
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>;
}
语法中的管道分隔符|表示“或者”的意思。
.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;
}
3. grid-area
grid-area
表示当前网格所占用的区域。在介绍grid-template-areas
属性的时候就演示过该属性,我们使用grid-template-areas
属性自定义一些网格区域,然后使用grid-area
属性让grid子项指定使用这些区域,就自动进行了区域分布。
grid-area
和grid-column/grid-row
作用都是grid子项的分布,但grid-area
语义要更好,识别度更佳,非常适合具有功能属性的布局区域(如头部,底部),同时,还支持非规则区域。
语法如下:
.item {
grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
其中:
<name>
:区域名称。由grid-template-areas
属性创建。<row-start> / <column-start> / <row-end> / <column-end>
:占据网格区域的纵横起始位置。
例如:
grid-area: 2 / 2 / auto / span 3;
/*等价于*/
grid-row-start: 2;
grid-row-end: auto;
grid-column-start: 2;
grid-column-end: span 3;
效果图:
4. justify-self
justify-self
表示单个网格元素的水平对齐方式。语法如下:
.item {
justify-self: stretch | start | end | center;
}
其中(假设文档流方向没有变):
stretch
:默认值,拉伸。表现为水平填充。start
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线左侧对齐显示。end
:表现为网格水平尺寸收缩为内容大小,同时沿着网格线右侧对齐显示。center
:表现为网格水平尺寸收缩为内容大小,同时在当前网格区域内部水平居中对齐显示。
5. align-self
align-self
指定了网格元素的垂直呈现方式,是垂直拉伸显示,还是上中下对齐,语法如下:
.item {
align-self: stretch | start | end | center;
}
其中(假设文档流方向为网页默认):
stretch
:默认值,拉伸。表现为垂直填充。start
:表现为网格垂直尺寸收缩为内容大小,同时沿着上网格线对齐显示。end
:表现为网格垂直尺寸收缩为内容大小,同时沿着下网格线对齐显示。center
:表现为网格垂直尺寸收缩为内容大小,同时在当前网格区域内部垂直居中对齐显示。
6. place-self
place-items
= align-self
+ justify-self
。(如果有兼容性顾虑,建议还是分开书写)语法如下:
.item {
place-items: <align-self> / <justify-self>;
}
这里顺序是align-self
在前,justify-self
在后。
五、其他Grid知识点
- 在Grid布局中,
float
,display:inline-block
,display:table-cell
,vertical-align
以及column-*
这些属性和声明对grid子项是没有任何作用的。 - Grid布局则适用于更大规模的布局(二维布局),而Flexbox布局最适合应用程序的组件和小规模布局(一维布局),关Flex布局请参见“写给自己看的display: flex布局教程”一文。
- 命名虽然支持中文,但由于CSS文件中文存在乱码的风险,所以……创新还是保守就看大家自己的抉择了。
- IE10-IE15虽然名义上支持Grid布局,但支持的是老版本语法(本文是介绍的全是2.0全新语法),还需要加-ms-私有前缀。
- 使用
z-index
控制层级:默认情况下回显示后来居上,但是如果设置后面的grid子项的z-index
比前面的grid子项低,则前面的grid子项会遮挡后面的grid子项
参考文章: