网格布局(Grid)是最强大的 CSS 布局方案。
它是一个二维布局,这意味着它可以处理 列 和 行 ,不像 flexbox 主要是布局系统。
基本介绍
学习 Grid 布局之前,需要了解一些基本概念。
容器(Grid Container)
在 容器 上使用 display: grid 即可定义。它是所有 网格元素(grid items) 的直接父级。
在此示例中,网格容器为 container :
<div class="container">
<div class="item item-1"></div>
<div class="item item-2"></div>
<div class="item item-3"></div>
</div>
元素(Grid Item)
网格容器的 直接后代 即为元素。
这里的 item 是网格元素,而 sub-item 不是:
<div class="container">
<div class="item"></div>
<div class="item">
<p class="sub-item"></p>
</div>
<div class="item"></div>
</div>
线(Grid Line)
线 构成网格结构的分界线。 它们可以是垂直或水平线,并且位于行和列的任意一侧。
这里的 黄线 是列网格线的示例:
轨迹(Grid Track)
轨迹 为两个相邻网格线之间的区域。它们为网格的行或列。
这里的 黄色区域 是网格轨迹。
单元格(Grid Cell)
行和列的交叉区域,称为"单元格"(cell)。
正常情况下,n行和m列会产生n x m个单元格。比如,2行3列会产生6个单元格。
区域(Grid Area)
四个网格线包围的总空间即为 区域 。网格区域可以包含任意数量的单元格。
这里是 行网格线 1、3 与 列网格线1、3 组成的区域:
Grid Container
- display: 定义一个
grid容器 - grid-template-columns grid-template-rows: 定义每一列宽(行高)
- grid-row-gap grid-column-gap grid-gap: 行间距,列间距
- grid-template-areas: 指定区域
- grid-auto-flow: 排列顺序 【row | column | row dense | column dense】
- justify-items align-items place-items: 单元格内容的对齐方式 【start | end | center | stretch】
- justify-content align-content place-content: 整个内容区域在容器里面的对齐方式 【start | end | center | stretch | space-around | space-between | space-evenly】
- grid-auto-columns grid-auto-rows: 分配额外区域
- grid-template: grid-template-columns、grid-template-rows 和 grid-template-areas 简写
- grid: grid-template-rows、grid-template-columns 、 grid-template-areas 、grid-auto-rows 、grid-auto-columns 、grid-auto-flow 简写 (过多不易区分,不建议)
dispaly
定义一个 grid 容器 , inline 还是 block 取决于给定的值。
.container {
display: grid | inline-grid;
}
grid-template-columns grid-template-rows
grid-template-columns 属性定义每一列的列宽,grid-template-rows 属性定义每一行的行高。
.container {
grid-template-columns: 40px 50px auto 50px 40px;
grid-template-rows: 25% 100px auto;
}
-
repeat()
有时候,重复写同样的值非常麻烦,尤其网格很多时。这时,可以使用
repeat()函数,简化重复的值。.container { display: grid; grid-template-columns: repeat(3, 33.33%); => 33.33%, 33.33%, 33.33% grid-template-rows: repeat(2, 100px 20px 80px); => 100px 20px 80px 100px 20px 80px } -
auto-fill 关键字
有时,单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用
auto-fill关键字表示自动填充。代码.container { display: grid; grid-template-columns: repeat(auto-fill, 100px); // 容器中每列100px自动填充 } -
fr 关键字
为了方便表示比例关系,网格布局提供了
fr关键字(fraction 的缩写,意为"片段")。如果两列的宽度分别为1fr和2fr,就表示后者是前者的两倍。代码.container { display: grid; grid-template-columns: 1fr 1fr; // 两列,宽度相同 }fr可以与绝对长度的单位结合使用,这时会非常方便。代码.container { display: grid; grid-template-columns: 150px 1fr 2fr; // 第一列150px, 第二列是第三列的一半 } -
minmax()
minmax()函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。.container { display: grid; grid-template-columns: 1fr 1fr minmax(100px, 1fr); // 第三列宽不小于100px,不大于1fr } -
auto 关键字
auto关键字表示由浏览器自己决定长度。grid-template-columns: 100px auto 100px; -
网格线的名称
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]; }上面代码指定网格布局为3行 x 3列,因此有4根垂直网格线和4根水平网格线。方括号里面依次是这八根线的名字。
网格布局允许同一根线有多个名字,比如
[fifth-line row-5]。 -
布局实例
grid-template-columns属性对于网页布局非常有用。两栏式布局只需要一行代码。.wrapper { display: grid; grid-template-columns: 70% 30%; }上面代码将左边栏设为70%,右边栏设为30%。
传统的十二网格布局,写起来也很容易。
grid-template-columns: repeat(12, 1fr);
grid-row-gap grid-column-gap grid-gap
grid-row-gap属性设置行与行的间隔(行间距),grid-column-gap属性设置列与列的间隔(列间距)
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
grid-column-gap: 10px;
grid-row-gap: 15px;
// 等同于
grid-gap: 15px 10px;
}
如果grid-gap省略了第二个值,浏览器认为第二个值等于第一个值。
Note: 根据最新标准,上面三个属性名的
grid-前缀已经删除,grid-column-gap和grid-row-gap写成column-gap和row-gap,grid-gap写成gap。
grid-template-areas
网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas 属性用于定义区域。
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
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";
}
上面代码中,顶部是页眉区域header,底部是页脚区域footer,中间部分则为main和sidebar。
如果某些区域不需要利用,则使用"点"(.)表示。
Note: 区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start,终止网格线自动命名为区域名-end。比如,区域名为
header,则起始位置的水平网格线和垂直网格线叫做header-start,终止位置的水平网格线和垂直网格线叫做header-end。
grid-auto-flow
默认情况下,容器的子元素默认排列顺序为 “先行后列”,那么可以设置 grid-auto-flow 属性值更改排列循序。
.container {
grid-auto-flow: row | column | row dense | column dense
}
row(default): 先行后列column: 先列后行row dense: 先行后列,紧密填充column dense: 先列后行,紧密填充
justify-items align-items place-items
justify-items 属性设置单元格内容的水平位置(左中右),align-items 属性设置单元格内容的垂直位置(上中下)。
place-items 属性是 align-items 属性和 justify-items 属性的合并简写形式。
.container {
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
// place-items 如果省略第二个值,则浏览器认为与第一个值相等
place-items: <align-items> <justify-items>;
}
start:对齐单元格的起始边缘。end:对齐单元格的结束边缘。center:单元格内部居中。stretch:拉伸,占满单元格的整个宽度(默认值)。
.container {
justify-items: start;
}
.container {
align-items: start;
}
Note:
justify-self与align-self可独立设置单个
justify-content align-content place-content
justify-content 属性是整个内容区域在容器里面的水平位置(左中右),align-content 属性是整个内容区域的垂直位置(上中下)。
.container {
justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
align-content: start | end | center | stretch | space-around | space-between | space-evenly;
// place-content 如果省略第二个值,浏览器就会假定第二个值等于第一个值。
place-content: <align-content> <justify-content>;
}
start- 对齐容器的起始边框。end- 对齐容器的结束边框。center- 容器内部居中。stretch- 项目大小没有指定时,拉伸占据整个网格容器。space-around- 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。space-between- 项目与项目的间隔相等,项目与容器边框之间没有间隔。space-evenly- 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
下面以 justify-content 为例:
grid-auto-columns grid-auto-rows
有时候,一些项目的 指定位置,在现有网格的外部。
grid-auto-columns 属性和 grid-auto-rows 属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与 grid-template-columns 和 grid-template-rows 完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
下面的例子里面,划分好的网格是3行 x 3列,但是,8号项目指定在第4行,9号项目指定在第5行。
.item-8 {
grid-row-start: 4;
grid-column-start: 2;
}
.item-9 {
grid-row-start: 5;
grid-column-start: 3;
}
Grid Item
- grid-column-start grid-column-end grid-row-start grid-row-end: 定位item
- grid-column grid-row: grid-column-start 和 grid-column-end 简写 || grid-row-start 和 grid-row-end 简写 斜线
/分隔 - grid-area: 指定 Item 放在哪一个区域,还可用作grid-row-start、grid-column-start、grid-row-end、grid-column-end 的简写 斜线
/分隔 - justify-self align-self place-self: 单元格内容的对齐方式(作用于自身) 【start | end | center | stretch】 ,与 justify-items align-items place-items 用法一致
grid-column-start grid-column-end grid-row-start grid-row-end
项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。
属性值可为网格线的名字,或者关键字 span 。
.item-1 {
grid-column-start: 2;
grid-column-end: 4;
}
// 等于
.item-1 {
grid-column-start: 2;
grid-column-end: span 2; span关键字,表示"跨越",即左右边框(上下边框)之间跨越多少个网格
}
grid-column-start属性:左边框所在的垂直网格线grid-column-end属性:右边框所在的垂直网格线grid-row-start属性:上边框所在的水平网格线grid-row-end属性:下边框所在的水平网格线
上面代码指定,1号项目的左边框是第二根垂直网格线,右边框是第四根垂直网格线。
上图中,只指定了1号项目的左右边框,没有指定上下边框,所以会采用默认位置,即上边框是第一根水平网格线,下边框是第二根水平网格线。
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;
}
grid-area
grid-area 属性指定项目放在哪一个区域。
.item-1 {
grid-area: e;
}
上面代码中,1号项目位于 e 区域,效果如下图。
grid-area属性还可用作 grid-row-start、grid-column-start、grid-row-end、grid-column-end的合并简写形式,直接指定项目的位置。
.item {
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
}
下面是一个例子。
.item-1 {
grid-area: 1 / 1 / 3 / 3;
}
justify-self align-self place-self
justify-self 属性设置单元格内容的水平位置(左中右),跟 justify-items 属性的用法完全一致,但只作用于单个项目。
align-self 属性设置单元格内容的垂直位置(上中下),跟 align-items 属性的用法完全一致,也是只作用于单个项目。
参考链接
- A Complete Guide to Grid by Chris House
- CSS Grid 网格布局教程 by 阮一峰