深入理解 Grid 布局
Grid 网格布局将页面划分成一个个网格,可以任意组合不同的网格,做出各种布局。与 Flex 的区别在于,Flex 布局是轴线布局,只能指定项目针对轴线的位置,可看作一维布局。而 Grid 布局则是将容器划分成行和列,产生单元格,然后指定项目所在的单元格,可看作二维布局,比 Flex 布局强大。
一、容器包裹层属性
1、grid-template-[columns/rows]
grid-template-columns
:设置每一列的列宽;grid-template-rows
:设置每一行的行高。
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<!-- ... -->
<div class="item">9</div>
</div>
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
}
效果如下:
1-1、百分比
上面可写成固定包裹层大小,单项使用百分比的形式,效果一样:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 33.33% 33.33% 33.33%;
grid-template-rows: 33.33% 33.33% 33.33%;
}
1-2、repeat()
可使用 repeat()
函数,简化重复的值。上面百分比可简写为:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
}
repeat()
除了重复值,还可以重复某种模式:
.container {
height: 300px;
display: grid;
grid-template-columns: repeat(2, 40px 50px 60px);
grid-template-rows: repeat(3, 33.33%);
}
效果如下:
1-3、auto-fill
auto-fill
关键字表示自动填充,在行(或列)上容纳尽可能多的固定单元格。举个例子:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: repeat(auto-fill, 70px);
grid-template-rows: repeat(auto-fill, 120px);
}
上面代码表示在宽高 300px 的容器中,每列按 70px 宽度的单元格自动填充,直到容器不能放置更多的列,按 120px 高度的单元格自动填充,直到容器不能放置更多的行,如果填充后的高度不够,会压缩最后一列/行,效果如下:
1-4、fr
网格布局提供了 fr
关键字(fraction 的缩写,意为"片段")表示倍数,如果两列的宽度分别为 1fr 和 2fr,就表示后者是前者的两倍。举个例子:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 2fr;
grid-template-rows: 1fr 1fr 1fr;
}
列指定了 2 列以 1:2 的比例自适应,行只指定了 3 个单元格的比例,剩下两个单元格会以最小高度显示,效果如下:
fr
也可以与具体尺寸一起使用:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 100px 1fr 2fr;
grid-template-rows: 1fr 1fr 1fr;
}
列指定了第一列固定 100px,剩下两列以 1:2 的比例自适应,行指定了 3 个单元格平均分,效果如下:
1-5、minmax()
minmax()
传入最小值和最大值,指定单元格尺寸范围。举个例子:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 1fr minmax(30px, 0.5fr);
grid-template-rows: 1fr 1fr 1fr;
}
列指定了第三列的宽度在 30px 到 0.5fr 之间,效果如下:
1-6、auto
auto
关键字表示由浏览器自己决定长度。举个例子:
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 1fr auto;
grid-template-rows: 1fr 1fr auto;
}
这里第 3 列与第 3 行指定 auto,使对应单元格以最小宽度/高度显示,效果如下:
1-7、网格线命名
可在 grid-template-[columns/rows] 中用方括号给对应位置的网格线命名,方便单项位置的存放:
.container {
display: grid;
grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
}
2、grid-template-areas
grid-template-areas
用于定义区域,一个区域由单个或多个单元格组成,一般结合子项的 grid-area 使用。可选值如下:
<grid-area-name>
ㅤ指定网格区域 grid-area 的名称;.
ㅤ表示一个空的网格单元;none
ㅤ表示没有定义网格区域。
举个例子:
<div class="container">
<div class="item-a">1</div>
<div class="item-a">2</div>
<div class="item-b">3</div>
<div class="item-c">4</div>
<div class="item-d">5</div>
</div>
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: auto;
grid-template-areas:
"a a a a"
"b b . c"
"d d d d";
}
.item-a {
grid-area: a;
}
.item-b {
grid-area: b;
}
.item-c {
grid-area: c;
}
.item-d {
grid-area: d;
}
效果如下:
3、[column/row]
-gap | gap
column-gap
:设置列间距;row-gap
:设置行间距;gap
:列间距与行间距的简写。
举个例子:
.container {
width: 300px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: repeat(3, calc((300px - 20px) / 3));
/* 写法一 */
column-gap: 10px;
row-gap: 10px;
/* 写法二 */
gap: 10px 10px;
/* 写法三 */
gap: 10px;
}
效果如下:
4、grid-auto-flow
grid-auto-flow
决定子元素的排列方式,默认为 row。
4-1、row | column
row
:按"先行后列"的顺序排列;column
:按"先列后行"的顺序排。
举个例子,默认 row 的排列如下:
设为 column:
.container {
/* ... */
grid-auto-flow: column;
}
效果如下:
4-2、[row/column]
dense
row dense
:按"先行后列"的顺序排列,并尽可能紧密填满;column
:按"先列后行"的顺序排,并尽可能紧密填满。
举个例子:
<div class="container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
}
.item1 {
grid-column-start: 1;
grid-column-end: 3;
}
.item2 {
grid-column-start: 1;
grid-column-end: 3;
}
没设 row dense 之前,效果如下:
设为 row dense:
.container {
/* ... */
grid-auto-flow: row dense;
}
效果如下:
column dense 同理。
4、justify-[content/items]
justify-content
:设置整个内容区域在包裹层中的水平位置;justify-items
:设置单元格内容的水平位置。
5、align-[content/items]
align-content
:设置整个内容区域的垂直位置;align-items
:设置单元格内容的垂直位置;
二、单项属性
1、grid-[column/row]
-[start/end]
grid-column-start
:设置单项左边框所在的垂直网格线;grid-column-end
:设置单项右边框所在的垂直网格线;grid-row-start
:设置单项上边框所在的水平网格线;grid-row-end
:设置单项下边框所在的水平网格线。
举个例子:
<div class="container">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.item1 {
grid-column-start: 2;
grid-column-end: 4;
}
.item2 {
grid-row-start: 2;
grid-row-end: 4;
}
效果如下:
这里除了使用纯数字指定是第几根网格线外,还可以使用 grid-template-[columns/rows] 中命名的网格线,也可以使用 span 关键字,表示水平跨越了多少个单元格,上面 .item1 的写法等同于:
.item1 {
grid-column-start: 2;
grid-column-end: span 2;
}
注意 span 后面要加空格。
2、grid-[column/row]
grid-column
:grid-column-start 和 grid-column-end 的合并简写;grid-row
:grid-row-start 和 grid-row-end 的合并简写;
上面的写法等同于:
.item1 {
grid-column: 2 / 4;
/* 或 */
grid-column: 2 / span 2;
}
.item2 {
grid-row: 2 / 4;
}
3、grid-area
grid-area
指定单项放在哪个区域,有两种用法:
- 配合上面 grid-template-areas 使用区域名称;
- 指定垂直/水平网格线的起始/终止位置,控制单项存放的区域,格式为:
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
上面 grid-template-areas 的例子可用下面 grid-area
控制网格线的写法:
<div class="container">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
<div class="item-4">4</div>
<div class="item-5">5</div>
</div>
.container {
width: 300px;
height: 300px;
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.item1 {
grid-area: 1 / 1 / 2 / span 4;
}
.item2 {
grid-area: 1 / 1 / 2 / span 4;
}
.item3 {
grid-area: 2 / 1 / 3 / span 2;
}
.item4 {
grid-area: 2 / 4 / 3 / span 1;
}
.item5 {
grid-area: 3 / 1 / 4 / 5;
}
效果如下:
4、[justify / align / place]
-self
justify-self
:设置单项单元格内容的水平位置;align-self
:设置单项单元格内容的垂直位置;place-self
:align-self 与 justify-self 的合并简写。