Skip to content

Gird 布局

标签:Web 前端
创建时间:2020/01/12 11:04:36

开启 Grid 布局

通过 display 属性即可开启 Grid 布局

css
.grid {
    display: grid;
}

行/列属性

可以使用 grid-template-rows 设置行属性,grid-template-columns 设置列属性。

例:绘制 3 行 3 列网格,行高和列宽均为 100px

css
.grid {
    display: grid;
    grid-template-rows: 100px 100px 100px;
    grid-template-columns: 100px 100px 100px;
}

或者是使用 repeat 函数快速实现等尺寸的多行多列布局。

css
.grid {
    display: grid;
    grid-template-rows: 100px 100px 100px;      
    grid-template-rows: repeat(3, 100px);       
    grid-template-columns: 100px 100px 100px;   
    grid-template-columns: repeat(3, 100px);    
}

对齐方式

水平对齐方式可以使用 justify-content 设置,属性值包括:

  • 起点对齐:start(默认值)
  • 终点对齐:end
  • 居中对齐:center
  • 两端对齐:space-between
  • 分散对齐:space-around
  • 还有 space-evenly 我也说不上来这是啥对齐

垂直对齐方式可以使用 align-content 设置,属性之包括:

  • 起点对齐:stretch(默认值)
  • 居中对齐:center
  • 两端对齐:space-between
  • 分散对齐:space-around
  • 还有 space-evenly 不知道啥对齐
css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(3, 100px);
    grid-template-columns: repeat(3, 100px);
    justify-content: center;
    align-content: center;
}

间距

可以通过 row-gapcolumn-gapgap 三个属性设置子元素之间的间距。

  • row-gap:设置行间距,不常用。
  • column-gap:设置列间距,不常用。
  • gap:当属性值有一个参数时表示行与列的边距均设为该值;如果有两个参数时,参数一表示行间距,参数二表示列间距。
css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(3, 100px);
    grid-template-columns: repeat(3, 100px);
    justify-content: center;
    align-content: center;
    gap: 10px 20px;
}

相对像素单位 fr

刚刚我们在设置行高和列宽时使用的是固定像素单位 px,这种写法不会随着父元素宽高变化而变化,但 fr 可以。

如何理解 fr ?我的理解是

比如我们把一个网格分为3列,每列分别占父元素的宽度的 1、2、3 份,那我们可以这样写:

css
.grid {
    grid-template-columns: 1fr 2fr 3fr;
}

因为 fr 有比例的意思,所以下面两段代码的效果相同,没有十年 脑血栓 写不出来第二段代码。

css
.grid {
    grid-template-columns: 1fr 2fr 3fr;      
    grid-template-columns: 2fr 4fr 6fr;      
}

显示网格与隐示网格

定义

我们通过 grid-template-rowsgrid-template-columns 设置的网格称为 显示网格,如果一个父元素的直接子节点数量大于网格数量,我们把超出的网格就称为 隐示网格

html
<div class="grid">
    <div class="item">1</div>
    <div class="item">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>

<style>
.grid {
    display: grid;
    grid-template-rows: repeat(3, 1fr);
    grid-template-columns: repeat(2, 1fr);
}
</style>

在这段代码中我们把网格设置为 3 行 2 列,总共 6 个格子,也就是说 1~6 是显示网格,7~9 是隐示网格。

隐示网格的宽高

我们可以通过 grid-auto-rows 设置隐示网格的行高

css
.grid {
    grid-auto-rows: 60px;
}

隐示网格的列宽见下文

动态列数

动态列数可以通过 repeat 函数和 minmax 函数实现,具体见下方代码:

css
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

repeat 函数的参数一是数量,参数二是尺寸

  • 参数一:auto-fill 表示尽可能多的显示列,也可以设置为 auto-fit,二者区别在于直接子元素在单行中的显示方式,具体看下图。
  • 参数二:minmax(200px, 1fr) 表示每个网格最小值为 200px,最大值为 1 份。

线的概念

如果把一个网格划分为 3 行 2 列,那么将产生 4 条竖线和 3 条横线,每根线都有两个编号,一个为正数,一个为负数,借助浏览器的 Elements 面板可查看线的布局及编号。

跨行与跨列

跨行

通过 grid-row-startgrid-row-end 属性设置元素的跨行区间,属性值可以是行编号或 span 关键字。

css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-row-start: 1;
        grid-row-end: 3;
    }
}
css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-row: 1 / 3;
    }
}
css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-row: 1 / span 2;
    }
}

跨列

通过 grid-column-startgrid-column-end 属性设置元素的跨列区间,属性值可以是列编号或 span 关键字。

通过编号跨列:

css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-column-start: 1;
        grid-column-end: 3;
    }
}

使用 span 关键字,span 表示跨多少列

css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-column-start: 1;
        grid-column-end: span 2;
    }
}

运行效果同上

简便写法,grid-column 属性是 grid-column-startgrid-column-end 的简写形式,属性值可以是列编号或 span 关键字。 grid-column-startgrid-column-end 之间用 / 分割。

css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-column: 1 / 3;
    }
}
css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-column: 1 / span 2;
    }
}

运行效果同上

合并写法

上面我们提到可以用 grid-rowgrid-column 可以实现跨行和跨列,其实这两个属性也可以合并为一个属性 grid-areagrid-area 属性适用于同时跨列和跨行的元素。

用 3 个 / 分隔 4 个属性值,分别是行开始编号、行结束编号、列开始编号、列结束编号,当然也可以使用 span 关键字。

css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-area: 1 / 1 / 3 / 3;
    }
}
css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(4, 1fr);
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;

    .item:nth-child(1) {
        grid-area: 1 / 1 / span 2 / span 2;
    }
}

命名写法

上面我们只针对一个子元素做了跨行和跨列,如果需要设置多个元素可以一个一个写,也可以通过给父元素设置 grid-template-areas 属性给每个区间命名,然后在子元素中设置 grid-area 属性,属性值为区间名称。

例:实现一个后端管理系统布局

css
.grid {
    height: 500px;
    display: grid;
    grid-template-rows: repeat(2, 60px) 1fr;
    grid-template-columns: 220px 1fr;
    gap: 10px;
    grid-template-areas:
        'header header'
        'menu tab'
        'menu main';

    .item:nth-child(1) {
        grid-area: header;
    }
    .item:nth-child(2) {
        grid-area: menu;
    }
    .item:nth-child(3) {
        grid-area: tab;
    }
    .item:nth-child(4) {
        grid-area: main;
    }
}

还有一种更牛逼的写法,可以通过 grid-template 整合 grid-template-rowsgrid-template-columnsgrid-template-areas

css
.grid {
    height: 500px;
    display: grid;
    gap: 10px;
    grid-template:
        'header header' 60px
        'menu tab' 60px
        'menu main' 1fr / 220px;

    .item:nth-child(1) {
        grid-area: header;
    }
    .item:nth-child(2) {
        grid-area: menu;
    }
    .item:nth-child(3) {
        grid-area: tab;
    }
    .item:nth-child(4) {
        grid-area: main;
    }
}

运行效果同上

排列方式

基本用法

启动 Grid 布局后,默认排列方式是行优先,当我们有 10 个子要素,但显示网格是这的是 3 行 2 列,这时隐示网格会继续向下增加行,直到 10 个子要素被填满。

当然,我们可以使用 grid-auto-flow 属性来设置排列方式。并且使用 grid-auto-columns 属性设置隐示网格的列宽。

css
.grid {
    display: grid;
    grid-template-rows: repeat(3, 80px);
    grid-template-columns: repeat(2, 200px);
    gap: 10px;
    grid-auto-flow: column;
    grid-auto-columns: 100px;

    .item:nth-child(n+7) {
        background: #FAD;
    }
}

紧凑模式

无论是行优先还是列优先,默认情况都是非紧凑模式

css
.grid {
    display: grid;
    grid-template-rows: repeat(3, 80px);
    grid-template-columns: repeat(3, 200px);
    gap: 10px;

    .item:nth-child(-n + 3) {
        grid-column: span 2;
    }
}

从上图中不难看出,第 4 个元素的位置有些不和常理,这时我们可以在设置 grid-auto-flow 属性的同时加上 dense 关键字。

css
.grid {
    display: grid;
    grid-template-rows: repeat(3, 80px);
    grid-template-columns: repeat(3, 200px);
    gap: 10px;
    grid-auto-flow: row dense;      

    .item:nth-child(-n + 3) {
        grid-column: span 2;
    }
}

元素排序

使用 order 属性可以设置元素排序,属性值可以是数字,数字越小越靠前。

css
.grid {
    display: grid;
    grid-template-rows: repeat(3, 80px);
    grid-template-columns: repeat(3, 200px);
    gap: 10px;
    grid-auto-flow: row dense;

    .item:nth-child(3) {
        order: -1;
    }
}

基于 MIT 许可发布