愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

Grid布局学习总结

Grid布局是CSS中除了flex布局外的另一强大的布局系统,相比flex,Grid布局更适合二维布局

一、基本概念

1、网格容器:声明display: grid的元素,所有网格项的直接父级元素
2、网格项:网格容器的直接子元素
3、网格线:构成网格结构的分界线,有水平线和垂直线,如图:
grid-1.png
4、网格轨道:两条相邻网格线之间的空间,可以想象成网格的列或行,如图:
grid-2.png
5、网格单元格:两个相邻的行网格线和两个相邻的列网格线所包围成的空间,如图:
grid-3.png
6、网格区域:任意4条网格线所包围的空间,如图:
grid-4.png


二、网格容器

对一个元素声明display: grid,即可定义为网格容器,并创建网格格式上下文,网格容器相关的display值有:

  • grid:生成一个块级网格
  • inline-grid:生成行级网格
  • subgrid:指定一个网格项为嵌套网格,如此其行/列大小会继承父级网格容器

注意:在网格容器上使用columnfloatclearvertical-align没有效果

1、定义网格

可以使用grid-template-columnsgrid-template-rows来定义网格和规定网格的大小,其语法为:

grid-template-columns: [line-name] <track-size> ...
grid-template-rows: [line-name] <track-size> ...

一些规则:
1)在未指定网格线名称的情况下,默认会自动分配数字名称,
2)可以使用fr单位,平分剩余空间
3)一条网格线可以有多个名字,用空格隔开
4)可以使用repeat()来简化写法,如1fr 1fr 1fr 200px表示为:repeat(3, 1fr) 200px
如下:

<div class="container">
    <!-- 9个DIV -->
</div>
.container {
    display: grid;
    width: 300px; height: 300px;
    grid-template-columns: 1fr [col-line1-end col-line2-start] 20% 1fr;
    grid-template-rows: 1fr 150px 1fr;
}

其图示为:
grid-5.png

2、grid-template-areas

通过grid-template-areas可以定义网格模板,这是一种可视化的网格定义方式,其具体用法为:
1)对网格容器指定grid-template-areas
2)对网格项目指定grid-area
其中,在grid-template-areas中,点号.(可以是多个点号)表示一个空的网格单元,none表示不定义网格空间,以下是一个实例:

<div class="container">
    <div class="header">header</div>
    <div class="content">content</div>
    <div class="sidebar">sidebar</div>
    <div class="footer">footer</div>
</div>
.container {
    display: grid;
    width: 800px; height: 400px;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: auto;
    grid-template-areas:
        "header header header header"
        "content content ... sidebar"
        "footer footer footer footer"
}
.container .header {
    grid-area: header;
}
.container .content {
    grid-area: content;
}
.container .sidebar {
    grid-area: sidebar;
}
.container .footer {
    grid-area: footer;
}

示意图如下:
grid-6.png
注意:grid-area命名的是网格区域而不是网格线,但是区域两端的网格线会自动命名,如例子中,header区域其起始行列网格线都是header-start,其结束网格线都是header-end

3、grid-template

用于定义grid-template-rowsgrid-template-columnsgrid-template-areas缩写,它的取值有三种情况:
1)none,三个属性都设为初始值
2)subgrid,将grid-template-rows/grid-template-columns设为subgridgrid-template-areas设为初始值
3)<grid-template-rows>/<grid-template-columns>,将grid-template-rowsgrid-template-columns设为相应的值,并设置grid-template-areanone
例如:

.container {
    display: block;
    width: 300px; height: 300px;
    grid-template: repeat(3, 1fr) / repeat(3, 1fr);
}

此外,还支持以下的写法:

.container {
    grid-template:
        [row1-start] "header header header" 25px [row1-end]
        [row2-start] "footer footer footer" 25px [row2-end]
        / auto 50px auto;
}

它相当于:

.container {
    grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
    grid-template-columns: auto 50px auto;
    grid-template-areas:
        "header header header"
        "footer footer footer"
}

4、grid-column-gap / grid-row-gap

两个属性可以指定网格线的大小(也即行列之间的间距宽度),实例:

.container {
    grid-template: repeat(3, 1fr) / repeat(3, 1fr);
    grid-column-gap: 10px;
    grid-row-gap: 15px;
}

图示如下:
grid-7.png
还可以使用简写形式,即:

grid-gap: <grid-row-gap> <grid-column-gap>

注意:如果只提供一个值,那么grid-row-gapgrid-column-gap都会设为这个值


三、弹性布局

使用Grid布局,也能够拥有像flex里那样灵活的功能,如下:

1、justify-items

设置沿着行轴线,网格项应该如何对齐,取值有:start/end/center/stretch,区别可直观图示如下:
grid-8.png

2、align-items

设置沿着列轴线,网格项应该如何对其,取值有:start/end/center/stretch,区别可直观图示如下:
grid-9.png

3、justify-content

设置沿着行轴线的网格容器内的网格的对其方式,取值有:start/end/center/stretch/space-around/space-between/space-evenly,区别可图示如下:
grid-10.png

4、align-content

取值与justify-content一致,但是是设置沿着列轴线的网格容器内的网格的对其方式


四、网格容器的其他属性

1、grid-auto-columns / grid-auto-rows

指定自动生成的网格轨道的大小(即超出定义范围,会创建隐式网格轨道),如下例子:

<div class="container">
    <div class="item1"></div>
    <div class="item2"></div>
    <div class="item3"></div>
    <div class="item4"></div>
</div>
.container {
    display: grid;
    grid-template: 60px 60px / 90px 90px;
}
.item4 {
    grid-column: 4 / 5;
    grid-row: 2 / 3;
}

由于定义的轨道是行轴线的1、2、3,列轴线的1、2、3,但是item4里指定在了行轴线2到3,列轴线4到5的位置,列轴线超出了定义范围,所以列轴线4和5被隐式创建了出来,其图示如下:
grid-11.png
这种情况下,默认的轨道大小是auto,所以3-4轨道和4-5轨道的大小均为auto
那么,若我们不想使得隐式轨道大小为auto,就可以设置grid-auto-columnsgrid-auto-rows,如:

.container {
    display: grid;
    grid-template: 60px 60px / 90px 90px;
    grid-auto-columns: 150px;
    grid-auto-rows: 60px;
}

其效果如下:
grid-12.png

2、grid-auto-flow

如果没有对一个网格项明确指定填充位置,自动放置算法会自动放置这些网格项,通过指定grid-auto-flow,可以告诉自动布局算法如何工作。其值有:
1)row:依次填充每行,根据需要添加新行
2)column:依次填充每列,根据需要添加新列
3)dense:出现较小的网格项时,尝试填充网格中较早的空缺

3、grid

这个属性是一系列属性的简写形式,包括:grid-template-rowsgrid-template-columnsgrid-template-areasgrid-auto-rowsgrid-auto-columnsgrid-auto-flow,此外还会将grid-column-gapgrid-row-gap设为初始值,grid的取值形式如下:
1)none:将所有字属性设为其初始值
2)<grid-template-rows> / <grid-template-columns>
3)<grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns> ]]:如果省略了grid-auto-columns,则用grid-auto-rows的值,如果两个值都省略了,则设为初始值
例子1:

.container {
    grid: 200px auto / 1fr auto 1fr;
}
/* 等价于 */
.container {
    grid-template-rows: 200px auto;
    grid-template-columns: 1fr auto 1fr;
    grid-template-areas: none;
}

例子2:

.container {
    grid:
        [row1-start] "header header header" 1fr [row1-end]
        [row2-start] "footer footer footer" 25px [row2-end]
        / auto 50px 50px;
}
/* 等价于 */
.container {
    grid-template-areas:
        "header header header"
        "footer footer footer";
    grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
    grid-template-columns: auto 50px 50px;
}


五、网格项属性

网格项即为网格容器的直接子元素

1、grid-column-start / grid-column-end / grid-row-start / grid-row-end

通过网格线来确定网格项的位置,取值有:

  • <line>:使用数字或者网格线名称来引用网格线
  • span <number>网格项跨越的网格轨道数量
  • span <name>网格项将跨越到它与提供的名字位置
  • auto:表示自动放置、自动跨度,默认会扩展一个网格轨道的宽度/高度

注意:
1)网格项可以重叠,使用z-index控制重叠顺序
2)grid-column为简写形式,相当于:grid-column: <grid-column-start> / <grid-column-end>grid-row同理,第二个参数可缺省,缺省时代表两者取一样的值

2、grid-area

网格项提供一个名称,供grid-template-areas引用。该属性也可以作为grid-row-start/grid-column-start/grid-row-end/grid-column-end的缩写,取值如下:

  • <name>:自定义一个名称
  • <row-start> / <column-start> / <row-end> / <column-end>

第二种形式,使用例子如:

.itemd {
    grid-area: 1 / col4-start / last-line / 6;
}

图示如:
grid-13.png

3、justify-self

设置单个网格项沿着行轴线方向的对齐方式,取值有:start/end/center/stretch,图示如:
grid-14.png

4、align-self

justify-self类似,但是是设置单个网格项沿着列轴线方向的对齐方式