理解grid网格布局

初步理解

Grid 布局即网格布局,是一种新的 CSS 布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。号称是最强大的的 CSS 布局方案,是一种 CSS 二维布局。
使用grid布局可以轻松实现类似这样的布局
grid布局展示
Grid 布局总体兼容性不错,IE10以下不支持。

grid与flex布局区别

flex 布局和 Grid 布局有实质的区别,flex 布局是一维布局,Grid 布局是二维布局。
flex 布局一次只能处理一个维度上的元素布局,一行或者一列。
Grid 布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到布局的目的。
Grid 布局比flex布局强大更灵活

巧妙解决flex布局的难题

在flex布局中,如果遇到最后一行是单数的情况,容易出现无法对齐的情况,这时候使用grid网格布局可以设置最后一行为左对齐。
flex布局难解决的情况
改用grid布局display:grid 是转为网格布局,这个是必须的

1
2
3
4
5
6
/* grid布局 两端对齐,最后一行左对齐*/
display: grid;
/* grid-template-columns:1fr | px 这是将网格分为几列,1fr是自适配单位,可以当成栅格*/
grid-template-columns: 1fr 1fr 1fr 1fr;
gap:30px 这是网格四周的间隔
注意:这三个属性是给父容器添加的,子元素,可以不用设置宽度,也不用设置margin间距即可完成如下布局。

grid布局,最后一行不是4的倍数,但是可以左对齐

grid布局

使用原理

Grid布局同样必须有父盒子,给父元素设置 display: grid 或 display: inline-grid 创建网格容器。

注意,设为网格布局以后,容器子元素项目的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效

  • 网格容器:通过将父元素的display属性设置为grid或inline-grid来创建网格容器。
  • 子元素的网格项目:网格容器中的每个子元素都成为网格项目。子元素可以指定各自在网格中的位置、大小以及对齐方式等。
  • 行与列:网格容器默认由行和列组成,可以通过CSS属性定义行和列的数量和大小。
  • 单元格:行和列的交叉区域,称为单元格(cell)
    • 正常情况下,n行和m列会产生n x m个单元格。比如,3行3列会产生9个单元格。
  • 网格线:划分网格的线,水平网格线划分出行,垂直网格线划分出列。
    • 正常情况下,n行有n + 1根水平网格线,m列有m + 1根垂直网格线,比如三行就有四根水平网格线。
    • 一般而言,网格线是从左到右,从上到下,1,2,3 进行编号排序。当然也可以从右到左,从下到上,按照 -1,-2,-3…顺序进行编号排序
  • 网格间距:可以在行和列之间添加间距,使布局更加美观。
    grip布局,网格线

容器属性(父元素属性)

display: 设置为grid或inline-grid启用网格布局

1
2
3
.container {
display: grid | inline-grid;
}

属性值:

  • grid:块级网格容器(数着排列)
  • inline-grid:行内网格容器(横着排列)

grid-template-columns和grid-template-rows

划分网格行和列,grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高
它们的值是多样的,设置比较相似的,下面以grid-template-columns 属性为例

  1. 可以使用绝对单位。也可以用百分比
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    .container {
    display: grid;
    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
    }
    .div {
    display: grid;
    grid-template-columns: 33.33% 33.33% 33.33%;
    grid-template-rows: 33.33% 33.33% 33.33%;
    }

repeat()函数

网格很多时,重复写同样的值非常麻烦,可以使用repeat()函数,简化重复的值。

  • repeat()接受两个参数,第一个参数是重复的次数(上例是3),第二个参数是所要重复的值。
    上面的代码用repeat()改写如下:
    1
    2
    3
    4
    5
    .container {
    display: grid;
    grid-template-columns: repeat(3, 33.33%);
    grid-template-rows: repeat(3, 33.33%);
    }
  • (很少用到) repeat()重复某种模式也可以
    • grid-template-columns: repeat(2, 100px 20px 80px);
    • 代码定义了6列,第一列和第四列的宽度为100px,第二列和第五列为20px,第三列和第六列为80px

auto-fill 关键字

有时单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充
下面代码表示列宽是100 px,但列的数量是不固定的,只要浏览器能够容纳得下,就可以放置元素

1
2
3
4
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
}

fr 关键字

fr 单位代表网格容器中可用空间的一等份。
grid-template-columns: 200px 1fr 2fr 表示第一个列宽设置为 200px,后面剩余的宽度分为两部分,宽度分别为剩余宽度的 1/3 和 2/3

1
2
3
4
5
6
.container {
display: grid;
grid-template-columns: 200px 1fr 2fr;
grid-gap: 5px;
grid-auto-rows: 50px;
}

minmax() 函数

minmax() 函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中,给网格元素一个最小和最大的尺寸。
minmax() 函数接受两个参数,分别为最小值和最大值。grid-template-columns: 1fr 1fr minmax(300px, 2fr) 的意思是,第三个列宽最少也是要 300px,但是最大不能大于第一第二列宽的两倍

1
2
3
4
5
6
.container {
display: grid;
grid-template-columns: 1fr 1fr minmax(300px, 2fr);
grid-gap: 5px;
grid-auto-rows: 50px;
}

auto 关键字

由浏览器决定长度
通过 auto 关键字,我们可以轻易实现三列或者两列布局
例如:grid-template-columns: 100px auto 100px
表示第一第三列为 100px,中间由浏览器决定长度

grid-row-gap、grid-column-gap和grid-gap属性

grid-row-gap 属性、grid-column-gap 属性分别设置行间距和列间距。 grid-gap 属性是两者的简写形式
grid-row-gap: 10px 表示行间距是 10px
grid-column-gap: 20px 表示列间距是 20px
grid-gap: 10px 20px 实现的效果是一样的

grid-template-areas 属性

grid-template-areas 属性用于定义区域,一个区域由一个或者多个单元格组成
一般这个属性跟网格元素的 grid-area 一起使用,我们在这里一起介绍。 grid-area 属性指定项目放在哪一个区域
例子:
下面代码表示划分出 个单元格,注意的是.符号代表空的单元格,就是没有用到该单元格

1
2
3
4
5
6
7
8
9
10
.container  {
display: grid;
grid-gap: 10px;
grid-template-columns: 120px 120px 120px;
grid-template-areas:
". header header"
"sidebar content content";
background-color: #fff;
color: #444;
}

下面代码表示将类 .sidebar .content .header所在的元素放在上面 grid-template-areas 中定义的 sidebar content header 区域中

1
2
3
4
5
6
7
8
9
10
11
12
.sidebar {
grid-area: sidebar;
}

.content {
grid-area: content;
}

.header {
grid-area: header;
}

grid-auto-flow 属性

  1. row和column
    划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。
    这个顺序由grid-auto-flow属性决定,默认值是row,先行后列(如图片左部分)
    grid-auto-flow: column 先列后行(如图片右部分)
    grid-auto-flow 属性
  2. row dense
    表示尽可能填充,而不留空白
    还可以设成row dense和column dense。这两个值主要用于,某些项目指定位置以后,剩下的项目怎么自动放置。

justify-items、align-items和place-items属性

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

1
2
3
4
.container {
justify-items: start | end | center | stretch;
align-items: start | end | center | stretch;
}

这两个属性的写法完全相同,都可以取下面这些值:

  • start:对齐单元格的起始边缘。
  • end:对齐单元格的结束边缘。
  • center:单元格内部居中。
  • stretch:拉伸,占满单元格的整个宽度(默认值)

justify-content、align-content和place-content 属性

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

1
2
3
4
.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;
}

这两个属性的写法完全相同,都可以取下面这些值

  • start:对齐容器的起始边框
  • end:对齐容器的结束边框
  • center:容器内部居中
  • space-around:每个项目两侧的间隔相等(项目之间的间隔比项目与容器边框的间隔大一倍)
  • space-between:项目与项目的间隔相等,项目与容器边框之间没有间隔
  • space-evenly:项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔
  • stretch:项目大小没有指定时,拉伸占据整个网格容器
    justify-content、align-content和place-content 属性
    justify-content、align-content和place-content 属性

grid-auto-columns和grid-auto-rows 属性

我多半用不到所以没写,需要的时候查下方参考文档和文章

项目属性(子元素属性)

grid-column-start、grid-column-end、grid-row-start和grid-row-end属性

可以指定网格项目所在的四个边框,分别定位在哪根网格线,从而指定项目的位置

grid-column-start 属性:左边框所在的垂直网格线
grid-column-end 属性:右边框所在的垂直网格线
grid-row-start 属性:上边框所在的水平网格线
grid-row-end 属性:下边框所在的水平网格线

grid-area属性

grid-area 属性指定项目放在哪一个区域,在上面介绍 grid-template-areas 的时候有提到过

justify-selfalign-self和place-self 属性

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

1
2
3
4
.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
}

ustify-selfalign-self和place-self 属性

高频属性

容器属性:

1
2
3
4
5
6
.container {
display: grid;
grid-template-columns: 1fr 200px; /* 列定义 */
grid-template-rows: 100px auto; /* 行定义 */
gap: 10px; /* 间距 */
}

项目属性:

1
2
3
4
.item {
grid-column: 1 / 3; /* 跨越两列 */
grid-row: 1; /* 定位到第一行 */
}

经典布局:

12列网格系统

grid-template-columns: repeat(12, 1fr)

杂志排版

grid-template-areas 定义区域

两栏式布局

只需要一行代码,左边栏设为70%,右边栏设为30%

1
2
3
4
.wrapper {
display: grid;
grid-template-columns: 70% 30%;
}

fr 实现等分响应式

fr 等分单位,可以将容器的可用空间分成想要的多个等分空间。利用这个特性,我们能够轻易实现一个等分响应式。
grid-template-columns: 1fr 1fr 1fr 表示容器分为三等分

repeat + auto-fit——固定列宽,改变列数量

grid-template-columns: repeat(auto-fit, 200px) 表示固定列宽为 200px,数量是自适应的,只要容纳得下,就会往上排列

1
2
3
4
5
6
7
8
.wrapper {
margin: 50px;
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
grid-gap: 10px 20px;
grid-auto-rows: 50px;
}

repeat+auto-fit+minmax 去掉右侧空白

右侧通常会留下空白,这是我们不希望看到的。如果列的宽度也能在某个范围内自适应就好了。minmax() 函数就帮助我们做到了这点。将 grid-template-columns: repeat(auto-fit, 200px) 改成 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) 表示列宽至少 200px,如果还有空余则一起等分

repeat+auto-fit+minmax-span-dense 解决空缺问题

每个网格元素的长度可能不相同,通过 span 关键字进行设置网格项目的跨度,grid-column-start: span 3,表示这个网格项目跨度为3
grid-auto-flow: row dense 表示尽可能填充,而不留空白

参考文章

这篇博客我结合了MDN web文档,B站视频,AI解答和以下博主的理解:
[1]本文参考了CSDN作者咸虾米_的grid布局文章

[2]本文参考了稀土掘金的grid布局文章稀土掘金
[3]这篇文章也很全面阮一峰-Grid 网格布局教程