Grid网格布局

1,612 阅读12分钟

一、介绍

Grid网格布局,是一个基于栅格的二维布局系统,相对于flex一维布局,Grid布局的功能更为强大

Grid布局可以将网页分成一个个网格,可以任意组合不同的网格,做出各种各样的布局

grid_01.png

二、网格布局

1.容器、项目、单元格、区域

容器:整个区域都是容器

项目:一格一格的单元格都是项目

单元格:cell

区域:area

行:row

列:column

grid_02.png

注:项目只能是容器的顶层子元素,不包含项目中的元素

2.行和列

容器内的水平区域为,垂直区域为

grid_03.png

3.网格线

划分网格的线,称为网格线。水平网格线划分出行,垂直网格线划分出列

n行有n+1根水平网格线,m列有m+1根垂直网格线

grid_04.png

4.网格布局生成属性

display: grid | inline-grid;

grid为块级网格布局,inline-grid为内联块级网格布局

三、容器属性

1.grid-template-columns、grid-template-rows

grid-template-columns属性定义每一列的列宽

grid-template-rows属性定义每一行的行高

值有几个就代表有几列或几行

grid-template-columns<rows>: length | percent(百分比) | auto | fr;

定义一个三行三列的网格,列宽和行高都是200px,使用了网格布局,基本无需单独控制子项的宽高

grid-template-columns: 200px 200px 200px;
grid-template-rows: 200px 200px 200px;

grid_05.png

百分比

grid-template-columns: 30% 40% 30%;
grid-template-rows: 30% 40% 30%;

grid_06.png

auto,子项会自适应容器剩余大小撑开

grid-template-columns: 200px 100px auto;
grid-template-rows: 200px auto 100px;

grid_07.png

fr,可以理解为比例值,将行与列都分成3份

grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;

grid_05.png

将第二行与第二列都划分为2份

grid-template-columns: 1fr 2fr 1fr;
grid-template-rows: 1fr 2fr 1fr;

grid_08.png

2.grid-template-areas

网格布局允许指定区域,一个区域由单个或多个单元格组成。grid-template-areas属性用于定义区域,以及配合项目上的属性grid-area

grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: 'f i b' 'd a g' 'e h c';

grid_09.png

当只给第一个grid-area

grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: 'a a b' 'a a b' 'c c c';

.item_01 {
    grid-area: a;
    background-color: red;
}

grid_10.png

当只有三个项目

grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-areas: 'a a b' 'a a b' 'c c c';

.item_01 {
    grid-area: a;
    background-color: red;
}

.item_02 {
    grid-area: b;
    background-color: orange;
}

.item_03 {
    grid-area: c;
    background-color: green;
}

grid_11.png

3.grid-template

grid-template属性是grid-template-columnsgrid-template-rowsgrid-template-areas这三个属性的简写形式。MDN上关于 grid-template相关的介绍

4.grid-row-gap、grid--column-gap

grid-row-gap属性设置行与行的间隔,目前逐渐被row-gap替代

gris-column-gap属性设置列与列的间隔,目前逐渐被column-gap替代

grid-row<column>-gap: length;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
row-gap: 20px;
column-gap: 20px;

grid_12.png

5.grid-gap

grid-gap属性是grid-column-gapgrid-row-gap的合并简写形式,目前逐渐被gap替代

grid-gap: <grid-row-gap> <grid-column-gap>;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
gap: 20px;

grid_12.png

6.justify-items、align-items

justify-items属性设置单元格内容的水平位置,align-items属性设置单元格内容的垂直位置,默认值都是stretch,在没给定子项宽高的情况下,会自动拉伸铺满整个容器

stretch当项目没设置宽度(高度)或是auto的时候,将会自动占满整个容器。当项目有宽高度是,默认值为start

justify-items<align-items>: start | end | center | stretch;

当项目给了宽度100px,不给默认拉伸是200px

grid_13.png

当出现这种情况时,便可以使用justify-itemsalign-items来对齐项目的位置

居中对齐

grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
justify-items: center;
align-items: center;

grid_14.png

尾部对齐

grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
justify-items: end;
align-items: end;

grid_15.png

7.place-items

place-items属性是align-items属性和justify-items属性的简写

place-items: <align-items> <justify-items>;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
place-items: center;

grid_14.png

8.justify-content、align-content

justify-content属性是整个内容区域在容器里面的水平位置

align-content属性是整个内容区域的垂直位置

默认为start

justify-content<align-content>: start | end | center | stretch | space-around | space-between | space-evenly;

结束位置对齐

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-content: end;
align-content: end;

grid_16.png

居中对齐

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-content: center;
align-content: center;

grid_17.png

两端对齐

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-content: space-between;
align-content: space-between;

grid_18.png

子项与子项之间间隔相等,子项与边框的间隔为子项与子项之间的一半

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-content: space-around;
align-content: space-around;

grid_19.png

子项与子项以及子项与边框之间的间隔相等

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-content: space-evenly;
align-content: space-evenly;

grid_20.png

9.place-content

place-content属性是align-content属性和justify-content属性的简写

place-content: <align-content> <justify-content>;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
place-content: center;

grid_17.png

10.justify-items、align-items与justify-content、align-content的注意点

在Grid网格布局中,一般justify-itemsalign-items一起使用,justify-contentalign-content一起使用

当子项的大小小于单元格的大小的时候,使用justify-itemsalign-items

例如单元格大小是100 * 100,而子项大小只有50 * 50,这种情况使用justify-itemsalign-items

grid_13.png

当容器大小大于单元格大小时,使用justify-contentalign-content

grid_21.png

11.显式网格与隐式网格

正常情况下,例如定义三行三列的网格,总共有9个元素,那这9个元素正好布满整个容器,所以这9个子项都是显式网格

grid-template-columns: 200px 200px 200px;
grid-template-rows: 200px 200px 200px;

grid_05.png

但若有超过9个子项,这些多出来的网格就是隐式网格,这些隐式网格会默认按照rows的方向进行排列,高度会自动拉伸铺满容器

grid_22.png

12.grid-auto-flow

grid-auto-flow属性决定网格的排列顺序

grid-auto-flow: row | column | row dense | column dense;

默认为先行后列

将顺序设置为先列后行,即grid-auto-flow: column

加上dense会没有空出的位置,有些情况下,会产生空出的情况

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-flow: column;

grid_23.png

13.grid-auto-rows、grid-auto-columns

若是先行后列的顺序,隐式网格的列宽默认和显式网格一样,行高则是拉伸铺满。若是先列后行的顺序,隐式网格的行高默认和显式网格一样。可以使用grid-auto-rowsgrid-auto-columns控制隐式网格的行高和列宽

先行后列的顺序下,设置隐式网格行高为50px

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-flow: row;
grid-auto-rows: 50px;

grid_24.png

先列后行的顺序下,设置隐式网格列高为50px

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-flow: column;
grid-auto-columns: 50px;

grid_25.png

隐式网格的行高也设置成100px,这样就和显式网格展示的大小一样

grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 100px;

grid_26.png

14.repeat()方法与auto-fill关键字

在定义网格的时候,写grid-template-columnsgrid-template-rows都是写多个重复值,即可使用repeat()去简化重复的值

repeat(number, length | percent | fr);

定义一个5行4列的网格

grid-template-columns: repeat(5, 100px);
grid-template-rows: repeat(4, 100px);

grid_27.png

也可具体的数值和repeat()函数一起使用

grid-template-columns: 200px repeat(2, 100px);
grid-template-rows: 200px repeat(2, 100px);

grid_28.png

明明网格4是可以继续在网格3的后面继续排列的,但这里会换行,是因为定义了三列。在单元格的大小是固定的,但是容器的大小不确定的情况下,使用每一行(或每一列)容纳可能多的单元格,便可以使用auto-fill关键字表示自动填充

grid-template-columns: repeat(auto-fill, 100px);
grid-template-rows: repeat(2, 100px);

grid_29.png

15.minmax()方法

minmax()函数产生一个长度范围,表示长度就在这个范围之中,它接受两个参数,分别为最小值和最大值

minmax(min, max);

定义一个列宽和行高不小于100px,不大于200px的网格

grid-template-columns: minmax(100px, 200px) minmax(100px, 200px) minmax(100px, 200px);
grid-template-rows: minmax(100px, 200px) minmax(100px, 200px) minmax(100px, 200px);
width: 600px;
height: 400px;

grid_30.png

minmax()方法可以和repeat()方法一起使用

grid-template-columns: repeat(3, minmax(100px, 200px));
grid-template-rows: repeat(3, minmax(100px, 200px));
width: 600px;
height: 400px;

grid_30.png

四、项目属性

1.grid-area

默认情况下,网格数字都是按顺序排列的,通过grid-area属性就可以指定项目放在哪一个区域,但前提是容器需要使用grid-template-areas属性指定了区域

网格1放到区域e

当前是只对项目1配置了grid-area: e

grid-template-columns: repeat(3, 200px);
grid-template-rows: repeat(3, 200px);
grid-template-areas: 'a b c' 'd e f' 'g h i';

.item_01 {
    grid-area: e;
    background-color: red;
}

grid_31.png

2.grid-column-start、grid-column-end和grid-row-start、grid-row-end与span关键字

这两对属性表示grid子项占据的区域的起始和终止位置,具体方法就是指定项目的四个边框,分别定位在哪根网格线

  • grid-column-start左边框所在的垂直网格线

  • grid-column-end右边框所在的垂直网格线

  • grid-row-start上边框所在的水平网格线

  • grid-row-end下边框所在的水平网格线

grid_35.png

grid_36.png

grid-column-startgrid-column-end

grid-column-start: 1;
grid-column-end: 3;

grid_32.png

grid-row-startgrid-row-end

grid-row-start: 2;
grid-row-end: 3;

grid_33.png

两对属性一起使用

grid-column-start: 2;
grid-column-end: 3;
grid-row-start: 2;
grid-row-end: 3;

grid_34.png

除了使用默认网格线名字,还可以直接命名网格线

grid-template-columns: [col1] 200px [col2] 200px [col3] 200px [col4];
grid-template-rows: [row1] 200px [row2] 200px [row3] 200px [row4];

.item_01 {
    grid-column-start: col2;
    grid-column-end: col3;
    grid-row-start: row2;
    grid-row-end: row3;
    background-color: red;
}

grid_37.png

grid_38.png

这两对属性还可以使用span关键字,表示跨越,即左右变宽(上下边框)之间跨越多少个网格

grid-column<row>-start: span number;
grid-column-start: span 2;

grid_32.png

grid-column-start: 2;
grid-column-end: span 2;

grid_39.png

3.grid-row、grid-column

grid-column属性是grid-column-startgrid-column-end的简写

grid-row属性是grid-row-startgrid-row-end的简写

grid-column: <start-line>/ <end-line>;
grid-row: <start-line>/ <end-line>;
.item_01 {
    grid-column: 1 / 3;
    grid-row: 1 / 2;
}

/* 等同于 */
.item_01 {
    grid-column-start: 1;
    grid-column-end: 3;
    grid-row-start: 1;
    grid-row-end: 2;
}

这两个属性之中,也可以使用span关键字,表示跨越多少个网格

.item_01 {
    grid-column: 1 / span 2;
    grid-row: 1 / span 2;
}

/* 等同于 */
.item_01 {
    grid-column: 1 / 3;
    grid-row: 1 / 3;
}

斜杆以及后面的部分可以省略,默认跨越一个网格

.item_01 {
    grid-column: 1;
    grid-row: 1;
}

grid-area也可以实现同样的效果

grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
grid-area: 2 / 3 / 2 / 3;

grid_40.png

4.justify-self、align-self

justify-self属性设置单元格内容的水平位置(左中右),跟justify-items属性的用法完全一致,但只作用于单个项目

align-self属性设置单元格内容的垂直位置(上中下),跟align-items属性的用法完全一致,只作用于单个项目

justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
  • start:对齐单元格的起始边缘
  • end:对齐单元格的结束边缘
  • center:单元格内部居中
  • stretch:拉伸,占满单元格的整个宽度(默认值)
.item_01 {
    justify-self: end;
    align-self: end;
    background-color: red;
}

grid_41.png

5.place-self

place-self属性是align-self属性和justify-self属性的简写

place-self: <align-self> <justify-self>;
.item_01 {
    place-self: center;
    background-color: red;
}

grid_42.png

五、布局案例

1.栅格化布局

利用grid布局可以轻松实现栅格化布局

.main {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: 200px;
    grid-auto-rows: 200px;
    gap: 20px;
    width: 600px;
    height: 600px;
    margin: 50px auto;
    padding: 20px;
    background-color: beige; 
}

.item { 
    display: flex;
    justify-content: center;
    align-items: center;
    color: #fff;
    font-size: 72px;
    text-align: center;
}

.col-1 {
    grid-area: auto/auto/auto/span 1;
    background-color: red;
}

.col-2 {
    grid-area: auto/auto/auto/span 2;
    background-color: orange;
}

.col-3 {
    grid-area: auto/auto/auto/span 3;
    background-color: green;
}

.col-4 {
    grid-area: auto/auto/auto/span 4;
    background-color: blue;
}

.col-5 {
    grid-area: auto/auto/auto/span 5;
    background-color: pink;
}

.col-6 {
    grid-area: auto/auto/auto/span 6;
    background-color: aqua;
}

.col-7 {
    grid-area: auto/auto/auto/span 7;
    background-color: darkgoldenrod;
}

.col-8 {
    grid-area: auto/auto/auto/span 8;
    background-color: blueviolet;
}

.col-9 {
    grid-area: auto/auto/auto/span 9;
    background-color: darkcyan;
}

.col-10 {
    grid-area: auto/auto/auto/span 10;
    background-color: blueviolet;
}

.col-11 {
    grid-area: auto/auto/auto/span 11;
    background-color: crimson;
}

.col-12 {
    grid-area: auto/auto/auto/span 12;
    background-color: rgb(183, 241, 241);
}
<div class="main">
    <div class="item col-6">6</div>
    <div class="item col-4">4</div>
    <div class="item col-8">8</div>
</div>

grid_43.png

2.不规则子项排列

grid_44.png

.list {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(4, 1fr);
    grid-template-areas: 'a1 a2 a2' 'a3 a2 a2' 'a4 a4 a5' 'a6 a7 a7';
    gap: 20px;
    width: 600px;
    height: 800px;
    margin: 50px auto;
    padding: 20px;
}

.item1 {
    grid-area: a1;
    background-color: pink;
}

.item2 {
    grid-area: a2;
    background-color: pink;
}

.item3 {
    grid-area: a3;
    background-color: skyblue;
}

.item4 {
    grid-area: a4;
    background-color: pink;
}

.item5 {
    grid-area: a5;
    background-color: pink;
}

.item6 {
    grid-area: a6;
    background-color: orange;
}

.item7 {
    grid-area: a7;
    background-color: orange;
}
<div class="list">
    <div class="item item1">1</div>
    <div class="item item2">2</div>
    <div class="item item3">3</div>
    <div class="item item4">4</div>
    <div class="item item5">5</div>
    <div class="item item6">6</div>
    <div class="item item7">7</div>
</div>