本文总结简化自阮一峰老师的《CSS Grid 网格布局教程》:www.ruanyifeng.com/blog/2019/0…
概述
类似这种布局
Grid布局与Flex布局
- 相同:通过单个属性控制多个项目的位置
- 不同:Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。
基本概念
容器和项目
内部采用网格布局的区域,称为“容器”,容器内被定位的子元素称为“项目”。
<div>
<div><p>1</p></div>
<div><p>2</p></div>
<div><p>3</p></div>
</div>
最外层<div>就是容器,内层的三个<div>就是项目。
注意:项目只能是容器的顶层子元素,不包含项目的子元素。 比如上面代码的<p>元素就不是项目(在他上面还有<div>作为顶层子元素)。Grid 布局只对项目生效。
单元格
行和列的交叉区域,称为"单元格"(cell)。
正常情况下,n行和m列会产生n*m个单元格。比如,3行3列会产生9个单元格。
网格线
划分网格的线,称为"网格线"(grid line)。水平网格线划分行,垂直网格线划分列。
正常情况下,n行有n+1根水平网格线,m列有m+1根垂直网格线,例如三行有四根水平网格线。
容器属性
display属性
display:grid指定容器内部采用网格布局
div {
display: grid;
}
效果如下:
默认情况下,盒子都是块级元素
但是有时候,我们想要让块级元素转化为行内元素并采用grid布局,就需要:
div {
display: inline-grid;
}
这样就可以在一行内排布一个grid布局的块级元素了
注意:设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align等设置都将失效。
grid-template-columns 和grid-template-rows
这两个属性用于定义行高(grid-template-rows)和列高(grid-template-columns)
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
意为列宽100px,行高100px;同样,也可以使用百分比表示长度。
repeat()
防止重复录入的麻烦,简化重复值。
.container {
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
}
repeat() 接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值(33.33%)
同时也可以进行某种模式的重复:
grid-template-columns: repeat(2, 100px 20px 80px);
这里以这种模式重复了2次:第一列和第四列的宽度为100px,第二列和第五列为20px,第三列和第六列为80px。
auto-fill关键字
当单元格大小固定,但是容器大小不固定。希望能容纳尽量多的单元格使用auto-fill表示自动填充
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
}
意为每列列宽100px,自动填充,直到容器不能容纳更多列
fr关键字
为方便进行比例设置,如果两列的宽度分别是 1fr 和 2fr,表示后者是前者的2倍
这里表示两列的宽度相同
.container {
display: grid;
grid-template-columns: 1fr 1fr;
}
fr可以与绝对长度的单位结合使用,这时会非常方便。
.container {
display: grid;
grid-template-columns: 150px 1fr 2f;
}
上面表示第一列宽度为150px,第二列宽度是第三列的一半。
minmax()
minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
上面代码中 ,minmax(100px, 1fr) 表示列宽不小于100px,不大于1fr。
auto关键字
auto关键字表示由浏览器自己决定长度。
grid-template-columns: 100px auto 100px;
上面代码中,第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width,且这个值大于最大宽度。
为网格线命名
grid-template-columns属性和grid-template-rows属性里面,还可以使用方括号,指定每一根网格线的名字,方便以后的引用。
.container {
display: grid;
grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
}
这里布局为3X3,4根水平线4根垂直线,并且分别命名。
grid-row-gap,grid-column-gap 和 grid-gap 属性
grid-row-gap属性设置行与行的间隔(行间距),grid-column-gap属性设置列与列的间隔(列间距)。
.container {
grid-row-gap: 20px;//行间距为20px
grid-column-gap: 20px;//列间距为20px
}
上面代码中,grid-row-gap用于设置行间距,grid-column-gap用于设置列间距。
这里介绍一个简写属性:grid-gap,他是grid-row-gap和grid-column-gap的合并写法,意义是:grid-gap: <grid-row-gap> <grid-column-gap>;
因此,上面一段CSS代码等同下面:
.container {
grid-gap: 20px 20px;
}
如果grid-gap省略了第二个值,浏览器认为第二个值等于第一个值。
此外,根据最新标准,上面三个属性名的grid-前缀已经删除,grid-column-gap和grid-row-gap写成column-gap和row-gap,grid-gap写成gap。
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';//分号加在此处
}
意为将划分出来的9个单元格分别定名为a,b,c,d...i九个区域。
同时可以做到多个单元格合并,写法如下:
grid-template-areas: 'a a a'
'b b b'
'c c c'
即可将9个单元格分为 a、b、c 三个部分
如果某些区域不需要利用,可以使用“点”(.)表示。例如:
grid-template-areas: 'a . c'
'. e f'
'g . i'
注意:
区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为区域名-start,终止网格线自动命名为区域名-end。
比如,区域名为header,则起始位置的水平网格线和垂直网格线叫做header-start,终止位置的水平网格线和垂直网格线叫做header-end
gird-auto-flow 属性
这个属性会决定网格的排列方法顺序。 默认放置顺序是“先行后列”(先摆满第一行再放第二行)
如图:
gird-auto-flow 属性默认值是row,可设置为 column 变成“先列后行”
如图:
当然,gird-auto-flow属性除了 row 和 column 以外,还有row dense和column dense两个属性值,可以用于:某些项目指定位置后,剩下项目的放置方法。
例如:下面例子中1号项目和2号项目各占据两个单元格,然后在默认的grid-auto-flow: row情况下,会产生下面这样的布局。
上图中,由于3号默认跟在2号后面,所以1号后面是空白。
现在修改为row dense,表示“先行后列尽量满”
之后效果如下:
同样的情况,我们试试“先列后行尽量满”
效果如下:
justify-items ,align-items和 place-items 属性
justify-items属性设置单元格内容的水平位置(左中右),align-items属性设置单元格内容的垂直位置(上中下)。
这两个属性都有同样的四个属性值:
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
用法如下:
.container {
justify-items: start;
}
水平居左
.container {
align-items: start;
}
垂直居上
内容位置也有简写方式:place-items
该属性是align-items属性和justify-items属性的合并简写形式:place-items: <align-items> <justify-items>;
若不写第二个值,则认为第二个值与第一个相同
justify-content,align-content 和place-content 属性
与上面属性类似,这三个属性作用是控制整个内容在容器内的位置(上面的属性是控制内容里,也就是单元格里的位置)。
并且这三个属性也有很多属性值:
- start :对齐容器的起始边框
- end:对齐容器的结束边框
- center:容器内部居中
- stretch :项目大小没有指定时,拉伸占据整个网格容器。
- space-around :每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
- space-between:项目与项目的间隔相等,项目与容器边框之间没有间隔。
- space-evenly:项目与项目的间隔相等,项目与容器边框之间没有间隔。
下面使用图例进行表示(仅以水平方向举例):
justify-content:start;
对齐容器的起始边框
justify-content:end;
对齐容器的结束边框
justify-content:center;
容器内部居中
justify-content:stretch;
项目大小没有指定时,拉伸占据整个网格容器。
justify-content:space-around;
每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。 。
justify-content:space-between;
项目与项目的间隔相等,项目与容器边框之间没有间隔。
justify-content:space-evenly;
项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
同样,他的简写:place-content
place-content:<align-content> <justify-content>
如果省略第二个值,浏览器就会假定第二个值等于第一个值。
grid-auto-columns 和 grid-auto-rows 属性
有时候,一些项目的指定位置,在现有网格的外部。比如网格只有3列,但是某一个项目指定在第5行。这时,浏览器会自动生成多余的网格,以便放置项目。
grid-auto-columns属性和grid-auto-rows属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns和grid-template-rows完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
举个栗子:
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 50px;
}
这里给容器内设置3X3的单元格,但是在第4行指定8号项目,第5行指定9号项目,由于设置 grid-auto-rows: 50px; 因此额外多出的两个单元格高度为50px。
项目属性
作用于单元格(项目)
grid-column-start,grid-column-end, grid-row-start 和 grid-row-end 属性。
通过指定项目的四个边框也就是网格线,就可以定位一个项目的位置。
- grid-column-start属性:左边框所在的垂直网格线
- grid-column-end属性:右边框所在的垂直网格线
- grid-row-start属性:上边框所在的水平网格线
- grid-row-end属性:下边框所在的水平网格线
举个例子: 这里仍然使用上面的3X3网格
.item-1 {
grid-column-start: 2;
grid-column-end: 4;
}
上述代码意为:1号项目左边框( grid-column-start)在第2根垂直网格线,右边框( grid-column-end)在第4根垂直网格线。
现在我们指定四个边框:
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 4;
}
此外,定位的四个属性还可以用span关键字,表示“跨越”,即左右边框/上下边框跨越多少个网格。
.item-1 {
grid-column-start: span 2;
}
上述代码意为跨越2个。 效果:
.item-1 {
grid-column-end: span 2;
}
也能做到同样的效果
grid-column 和 grid-row 属性
grid-column属性是grid-column-start和grid-column-end的合并简写形式
grid-row属性是grid-row-start属性和grid-row-end的合并简写形式。
.item-1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
/* 等同于 */
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
/* 等同于 */
.item-1 {
grid-column: 1 / span 2;
grid-row: 1 / span 2;
}
简写过程中需要用 “/” 分开两数值(网格线名)
同样,也可省略“end结束”数值
.item-1 {
grid-column: 1;
grid-row: 1;
}
grid-area 属性
用于指定项目放在哪个区域
.item-1 {
grid-area: e;
}
让项目1定位于e区域
.item {
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
}
上面的项目1可表示为:
.item-1 {
grid-area: 2 / 2 / 3 / 3;
}
上下对比着看,分别为顺时针的:“上左下右”
justify-self ,align-self 和 place-self 属性
justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目。
align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,也是只作用于单个项目。
同样具有四个值:
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
举个栗子:
.item-1 {
justify-self: start;
}
他的简写:place-self: <align-self> <justify-self>;
例如:place-self: center center;
如果省略第二个值,place-self属性会认为这两个值相等。