CSS | 是时候学习 Grid 布局了!

在前端开发中,创建灵活且响应式的布局是非常重要的。为了实现这一目标,Grid 网格布局成为了一种强大的工具。它提供了一种直观且灵活的方式来构建网页布局,本文将从Grid的基本概念入手,介绍Grid网格布局中的常用属性和功能。那么下面我们一起来探索这个强大且灵活的布局方式吧!

Flex与Grid

  • Flex布局是一维的排版方式,也就是说一次只能控制一个方向(水平方向或者垂直方向),如果需要控制另一个方向需要再添加一层flexbox容器。
  • Grid布局是二维的排版方式,一次能控制两个方向,通过将容器分成行和列,便可定义容器内元素的位置。

基本概念

行与列的概念(row & column)

  • 水平区域------行
  • 垂直区域------列

单元格(cell)

  • 行和列交叉的区域就为一个单元格
  • 正常情况下,n行和m列产生m*n个单元格->5行5列=5*5=25个单元格

网格线(grid line)

  • 划分网格的线,称为"网格线"(grid line)。

  • 水平网格线划分出行,垂直网格线划分出列。

  • 正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线。

    比如下图5行5列的情况下,有6根水平网格线和6根垂直网格线。

启用Grid布局

首先需要准备一个容器元素

html 复制代码
<div class="container"></div>

然后设定容器的display:grid即可

css 复制代码
.container {
    display: grid;
    width: 500px;
    height: 500px;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
}

❕注:Grid布局分为display:griddisplay: inline-gridgrid下容器元素都是块级元素,而inline-grid则是行内元素。

行高与列宽(grid-template-rows/columns

  • grid-template-rows属性:定义每一行的行高
  • grid-template-columns属性:定义每一列的列宽

比如,下面将grid-template-rowsgrid-template-columns都设定为5个100px,中间用空格隔开,grid-template-rows代表垂直方向 分割出5个高度为100px的空间,grid-template-columns代表水平方向 分割出5个高度为100px的空间。

css 复制代码
.container {
  display: grid;
  grid-template-rows: 100px 100px 100px 100px 100px;
  grid-template-columns: 100px 100px 100px 100px 100px;
  width: 500px;
  height: 500px;
  border: 1px solid rgb(0, 0, 0);
  background-color: #eee;
}

repeat()函数

如果觉得定义行高(grid-template-rows)以及列宽(grid-template-columns)的时候重复书写某个值很麻烦,那么就可以考虑使用repeat()函数。

语法:

repeat(<length>, [<value> | <mode>])

  • 参数1length:需要重复的次数
  • 参数2[<value> | <mode>]:需要重复的值,可以是百分比、具体的值或者是某种模式

比如上面的定义行高与列宽中的代码就可以改写为下面这样

css 复制代码
.container {
  display: grid;
  grid-template-rows: repeat(5, 100px);
  grid-template-columns: repeat(5, 100px);
  width: 500px;
  height: 500px;
  border: 1px solid rgb(0, 0, 0);
  background-color: #eee;
}
  • repeat()可以和正常的设定值混用
css 复制代码
grid-template-rows: 100px repeat(2, 100px 100px);

fr 关键字

如果想按照比例分配行高(grid-template-rows)以及列宽(grid-template-columns)的值,那么就可以使用fr关键字(Fraction,意为"片段")。

  • fr表示比例,1fr表示占1份。
  • 如果将上面的grid-template-rows: repeat(5, 100px)改为grid-template-rows: repeat(5, 1fr),即表示即各占5分之1的空间。
  • fr关键字同样可以和正常的设定值混用
css 复制代码
grid-template-rows: 1fr repeat(2, 1fr 1fr);

auto-fill关键字

有时,单元格的大小是固定的,但是容器的大小不确定。

如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充。

css 复制代码
grid-template-columns: repeat(auto-fill, 100px);

上面代码表示每列宽度100px,然后根据容器的宽度自动填充,直到容器不能放置更多的列。

HTML:

html 复制代码
<div class="container">
  <div class="number cell1">1</div>
  <div class="number cell2">2</div>
  <div class="number cell3">3</div>
  <div class="number cell4">4</div>
  <div class="number cell5">5</div>
  <div class="number cell6">6</div>
  <div class="number cell7">7</div>
  <div class="number cell8">8</div>
  <div class="number cell9">9</div>
</div>

CSS:

css 复制代码
.container {
  display: grid;
  width: 500px;
  height: 500px;
  background-color: #eee;
  border: 1px solid rgb(0, 0, 0);
  grid-template-rows: repeat(5, 100px);
  grid-template-columns: repeat(auto-fill, 200px);
}

.cell1 {
  background-color: blue;
}

.cell2 {
  background-color: yellow;
}

.cell3 {
  background-color: orange;
}

.cell4 {
  background-color: black;
  color: white;
}

.cell5 {
  background-color: #c077af;
}

.cell6 {
  background-color: #f8d29d;
}

.cell7 {
  background-color: #b4a87f;
}

.cell8 {
  background-color: #d0e4a8;
}

.cell9 {
  background-color: #4dc7ec;
}

效果图:

auto关键字

auto关键字可以让浏览器自己决定长度。

css 复制代码
grid-template-columns: 100px auto 100px;

上面的意思是,第二列的宽度,等于该列单元格的最大宽度。

HTML:

html 复制代码
<div class="container">
    <div class="number cell1">1</div>
    <div class="number cell2">2</div>
    <div class="number cell3">3</div>
    <div class="number cell4">4</div>
</div>

CSS:

css 复制代码
.container {
    display: grid;
    width: 500px;
    height: 500px;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
    grid-template-rows: repeat(5, 100px);
    grid-template-columns: 100px auto 100px;
}

效果图:

❕注:除非单元格内容设置了min-width,且这个值大于最大宽度。

指定元素的位置

下面给容器添加两个元素,设置对应的背景色

HTML:

html 复制代码
<div class="container">
    <div class="number cell1">1</div>
    <div class="number cell2">2</div>
</div>

CSS:

css 复制代码
.container {
    width: 500px;
    height: 500px;
    display: grid;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
    grid-template-rows: 100px 100px 100px 100px 100px;
    grid-template-columns: 100px 100px 100px 100px 100px;
}

.number {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: content-box;
    border: 1px solid rgb(117, 117, 117);
    border-radius: 5px;
    box-shadow: 0px 5px 3px #000;
    font-size: 35px;
    font-weight: 800;
}

.cell1 {
    background-color: blue;
}

.cell2 {
    background-color: yellow;
}

效果如图所示:

这个是默认没有定义元素位置的情况,如果想要指定元素位置需要用到grid-rowgrid-column属性。

grid-rowgrid-column

grid-rowgrid-column本身是复合属性。

  • grid-row指定**垂直方向**上的范围

  • grid-column指定**水平方向**上的范围

  • grid-row属性的组成部分:

    • grid-row-start:上边框所在的水平网格线
    • grid-row-end:下边框所在的水平网格线
  • grid-column属性的组成部分:

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

如果想使用grid-row,首先指定grid-row-start,然后再指定grid-row-end即可,语法如下:

css 复制代码
.cell-1 {
  grid-row: <start-line> / <end-line>
}

gird-column也是如此,也是先指定grid-column-start,然后再指定grid-column-end,语法如下:

css 复制代码
.cell-1 {
 grid-column: <start-line> / <end-line>;
}

有了这些前置知识后,现在就可以指定元素的位置了,打个比方,如果想占据让蓝色占据以及黄色占据下图所示的区域

首先来看蓝色的色块:

  • 水平方向上的范围是从1到3,对应的grid-column的值为1 / 3
  • 竖直方向上的范围是1到4,对应的grid-row的值为1 / 4

然后看看黄色的色块:

  • 水平方向上的范围是从3到6,对应的grid-column的值为3 / 6
  • 竖直方向上的范围是4到6,对应的grid-row的值为4 / 6

写出对应的CSS,看看效果:

css 复制代码
.cell1 {
    background-color: blue;
    grid-column: 1 / 3;
    grid-row: 1 / 4;
}

.cell2 {
    background-color: yellow;
    grid-column: 3 / 6;
    grid-row: 4 / 6;
}

grid-area(复合属性)

除了可以用grid-columngrid-row指定元素的位置,还可以使用grid-area属性。

  • 该属性为grid-columngrid-row的复合属性

我们直接上代码:

css 复制代码
.cell2 {
    background-color: yellow;
    /* grid-column: 3 / 6;
    grid-row: 4 / 6; */
    grid-area: 4 / 3 / 6 / 6;
}

效果和原本的是一样的,grid-area的设置顺序是:

  1. grid-row的第一个值
  2. grid-column的第一个值
  3. grid-row的第二个值
  4. grid-column的第二个值

可以理解为"坐标",即左上角、右下角坐标。

不过个人不太喜欢用,因为没有grid-rowgrid-column看上去直观。

span关键字

grid-rowgrid-column的设定值是由第几至第几,比如第1至第5:1 / 5

实际在开发过程中是不会有之前图片上那样的标尺的,一遍一眼就可以看出对应的编号的。

因此Grid布局提供了span关键字,span是延伸的意思,所以可以理解为:

  • 第几开始延伸多少格

所以我们可以将蓝色块的代码修改为下面这样:

css 复制代码
.cell1 {
    background-color: blue;
    grid-column: 1 / span 3;
    grid-row: 1 / span 2;
}
  • 这里的grid-column意为:从1向后延伸3格
  • 这里的grid-row意为:从1向后延伸2格

效果如下图:

给网格线(grid line)起别名

实际上我们可以给**网格线(grid line)**起别名,代码如下:

css 复制代码
.container {
    display: grid;
    grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
    grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
    width: 500px;
    height: 500px;
    border: 1px solid rgb(0, 0, 0);
    background-color: #eee;
}

对应的代码中也可以使用别名了

css 复制代码
.cell1 {
    background-color: blue;
    grid-column: X1 / X6;
    grid-row: Y2 / Y4;
}

给单元格起别名(grid-template-areas

  • 使用grid-template-areas就可以给单元格起别名

首先我们继续给容器增加两个元素

HTML:

html 复制代码
<div class="container">
    <div class="number cell1">1</div>
    <div class="number cell2">2</div>
    <div class="number cell3">3</div>
    <div class="number cell4">4</div>
</div>

CSS:

css 复制代码
.cell1 {
    background-color: blue;
}

.cell2 {
    background-color: yellow;
}

.cell3 {
    background-color: orange;
}

.cell4 {
    background-color: black;
    color: white;
}

效果图:

现在通过grid-template-areas给容器的各个单元格命名,构建出一个经典的网页布局吧!

css 复制代码
.container {
    width: 500px;
    height: 500px;
    display: grid;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
    grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
    grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
    grid-template-areas: 
    "h h h h h"
    "n m m m m"
    "n m m m m"
    "n m m m m"
    /* 写点可以忽略该格子 */
    ". f f f ."
    ;
}

现在对容器中的元素使用grid-area属性,并指定对应grid-template-areas中为方格起的别名即可实现自动填充无需再传入坐标了!

css 复制代码
.cell1 {
    background-color: blue;
    grid-area: h;
}

.cell2 {
    background-color: yellow;
    grid-area: n;
}

.cell3 {
    background-color: orange;
    grid-area: m;
}

.cell4 {
    background-color: black;
    color: white;
    grid-area: f;
}

❕注意:repeat()不适用于grid-template-areas中。

行间距与列间距(grid-row/column-gap

如果觉得所有元素紧贴在一起不太好,Grid布局还提供了grid-row-gapgrid-column-gap来增加元素间的行间距与列间距

  • grid-row-gap属性设置行与行的间隔(行间距)
  • grid-column-gap属性设置列与列的间隔(列间距)

下面我们将刚才写的经典布局的案例的CSS加上这两个属性

css 复制代码
.container {
    display: grid;
    width: 500px;
    height: 500px;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
    grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
    grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
    grid-template-areas: 
    "h h h h h"
    "n m m m m"
    "n m m m m"
    "n m m m m"
    /* 写点可以忽略该格子 */
    ". f f f ."
    ;
    row-gap: 10px;
    column-gap: 10px;
}

可以看到内部增加了列间距与行间距后将容器撑大了,所以容器的宽高也需要修改下:

css 复制代码
.container {
    display: grid;
    /* width: 500px;
    height: 500px; */
    width: 540px;
    height: 540px;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
    grid-template-rows: [Y1] 100px [Y2] 100px [Y3] 100px [Y4] 100px [Y5] 100px [Y6];
    grid-template-columns: [X1] 100px [X2] 100px [X3] 100px [X4] 100px [X5] 100px [X6];
    grid-template-areas: 
    "h h h h h"
    "n m m m m"
    "n m m m m"
    "n m m m m"
    /* 写点可以忽略该格子 */
    ". f f f ."
    ;
    row-gap: 10px;
    column-gap: 10px;
}

现在看上去就正常了!

grid-auto-flow 关键字

  • Grid布局提供了grid-auto-flow用于控制容器内元素的排列方向(类似Flex布局中的flex-direction+flex-warp:warp的效果)

  • 默认值为row,默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。

  • 设置为column时,表示"先列后行",即先填满第一列,再开始放入第二列,具体参考下图数字的排列顺序。

设置单元格中的元素/内容的位置

justify-itemsalign-items

  • justify-items属性设置单元格内容的水平位置(左中右)。
  • align-items属性设置单元格内容的垂直位置(上中下)。

可选值:

  • start:对齐单元格的起始边缘。

  • end:对齐单元格的结束边缘。

  • center:单元格内部居中。

  • stretch:拉伸,占满单元格的整个宽度(默认值)。

比如现在想让容器中元素的编号向左上角对齐可以这么写:

CSS:

css 复制代码
.number {
    /* display: flex;
    align-items: center;
    justify-content: center; */

    display: grid;
    justify-items: start;
    align-items: start;

    box-sizing: content-box;
    border: 1px solid rgb(117, 117, 117);
    border-radius: 5px;
    box-shadow: 0px 5px 3px #000;
    font-size: 35px;
    font-weight: 800;
}

效果:

place-items(复合属性)

  • 该属性为 justify-itemsalign-items的复合属性

  • 语法

    xml 复制代码
    place-items: <align-items> <justify-items>;

比如刚才的代码就可以简写为:place-items: start start;

justify-selfalign-self

  • justify-self属性设置单元格内容的水平位置(左中右),与justify-items用法完全一致,但只作用于单个元素。
  • align-self属性设置单元格内容的垂直位置(上中下),与align-items用法完全一致,但只作用于单个元素。

比如只想要第二个元素向左下角对其,就可以这么写:

CSS:

css 复制代码
.cell1 {
    background-color: yellow;
    align-self: start;
    justify-self: start;
}

效果:

place-self(复合属性)

  • 该属性为align-self属性和justify-self属性的复合属性。

  • 语法:

    css 复制代码
    place-self: <align-self> <justify-self>;

所以刚才的代码可以简写为这样:place-self: end end;

设置整个容器中内容的位置

justify-contentalign-content

  • justify-content属性是整个内容区域在容器里面的水平位置(左中右)。
  • align-content属性是整个内容区域的垂直位置(上中下)。

取值:

注:下面的图都以justify-content属性为例

CSS:

css 复制代码
.container {
    display: grid;
    width: 600px;
    height: 600px;
    background-color: #eee;
    border: 1px solid rgb(0, 0, 0);
    grid-template-rows: repeat(5, 100px);
    grid-template-columns: repeat(5, 100px);
    grid-auto-flow: row;
}
  • start - 对齐容器的起始边框。 默认值

  • end - 对齐容器的结束边框。

  • center - 容器内部居中。

  • stretch - 项目大小没有指定时,拉伸占据整个网格容器。

    移除grid-template-rows以及grid-template-columns

  • space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。

  • space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔。

  • space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。

place-content(复合属性)

  • 该属性是align-contentjustify-content的复合属性

  • 语法:

    css 复制代码
    place-content: <align-content> <justify-content>

注意:如果省略第二个值,浏览器就会假定第二个值等于第一个值。

练习小游戏

GRID GARDEN-链接

参考文献

相关推荐
生椰拿铁You3 分钟前
09 —— Webpack搭建开发环境
前端·webpack·node.js
狸克先生14 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
baiduopenmap28 分钟前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish36 分钟前
小程序webview我爱死你了 小程序webview和H5通讯
前端
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_1 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
guokanglun1 小时前
空间数据存储格式GeoJSON
前端
zhang-zan1 小时前
nodejs操作selenium-webdriver
前端·javascript·selenium
猫爪笔记2 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html
brief of gali2 小时前
记录一个奇怪的前端布局现象
前端