grid 布局?归我啦!
理解grid网格布局
初步理解
Grid 布局即网格布局,是一种新的 CSS 布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。号称是最强大的的 CSS 布局方案,是一种 CSS 二维布局。
使用grid布局可以轻松实现类似这样的布局
Grid 布局总体兼容性不错,IE10以下不支持。
grid与flex布局区别
flex 布局和 Grid 布局有实质的区别,flex 布局是一维布局,Grid 布局是二维布局。
flex 布局一次只能处理一个维度上的元素布局,一行或者一列。
Grid 布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到布局的目的。
Grid 布局比flex布局强大更灵活
巧妙解决flex布局的难题
在flex布局中,如果遇到最后一行是单数的情况,容易出现无法对齐的情况,这时候使用grid网格布局可以设置最后一行为左对齐。
改用grid布局display:grid 是转为网格布局,这个是必须的
1 | /* grid布局 两端对齐,最后一行左对齐*/ |
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…顺序进行编号排序
- 网格间距:可以在行和列之间添加间距,使布局更加美观。
容器属性(父元素属性)
display: 设置为grid或inline-grid启用网格布局
1 | .container { |
属性值:
- grid:块级网格容器(数着排列)
- inline-grid:行内网格容器(横着排列)
grid-template-columns和grid-template-rows
划分网格行和列,grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高
它们的值是多样的,设置比较相似的,下面以grid-template-columns 属性为例
- 可以使用绝对单位。也可以用百分比
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 | .container { |
fr 关键字
fr 单位代表网格容器中可用空间的一等份。
grid-template-columns: 200px 1fr 2fr 表示第一个列宽设置为 200px,后面剩余的宽度分为两部分,宽度分别为剩余宽度的 1/3 和 2/3
1 | .container { |
minmax() 函数
minmax() 函数产生一个长度范围,表示长度就在这个范围之中都可以应用到网格项目中,给网格元素一个最小和最大的尺寸。
minmax() 函数接受两个参数,分别为最小值和最大值。grid-template-columns: 1fr 1fr minmax(300px, 2fr) 的意思是,第三个列宽最少也是要 300px,但是最大不能大于第一第二列宽的两倍
1 | .container { |
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
表示行间距是 10pxgrid-column-gap: 20px
表示列间距是 20pxgrid-gap: 10px 20px
实现的效果是一样的
grid-template-areas 属性
grid-template-areas 属性用于定义区域,一个区域由一个或者多个单元格组成
一般这个属性跟网格元素的 grid-area 一起使用,我们在这里一起介绍。 grid-area 属性指定项目放在哪一个区域
例子:
下面代码表示划分出 个单元格,注意的是.
符号代表空的单元格,就是没有用到该单元格
1 | .container { |
下面代码表示将类 .sidebar .content .header所在的元素放在上面 grid-template-areas 中定义的 sidebar content header 区域中
1 | .sidebar { |
grid-auto-flow 属性
- row和column
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。
这个顺序由grid-auto-flow属性决定,默认值是row,先行后列(如图片左部分)grid-auto-flow: column
先列后行(如图片右部分) - row dense
表示尽可能填充,而不留空白
还可以设成row dense和column dense。这两个值主要用于,某些项目指定位置以后,剩下的项目怎么自动放置。
justify-items、align-items和place-items属性
justify-items属性设置单元格内容的水平位置(左中右),align-items属性设置单元格内容的垂直位置(上中下)
1 | .container { |
这两个属性的写法完全相同,都可以取下面这些值:
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)
justify-content、align-content和place-content 属性
justify-content属性是整个内容区域在容器里面的水平位置(左中右),align-content属性是整个内容区域的垂直位置(上中下)。
1 | .container { |
这两个属性的写法完全相同,都可以取下面这些值
- start:对齐容器的起始边框
- end:对齐容器的结束边框
- center:容器内部居中
- space-around:每个项目两侧的间隔相等(项目之间的间隔比项目与容器边框的间隔大一倍)
- space-between:项目与项目的间隔相等,项目与容器边框之间没有间隔
- space-evenly:项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔
- stretch:项目大小没有指定时,拉伸占据整个网格容器
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 | .item { |
高频属性
容器属性:
1 | .container { |
项目属性:
1 | .item { |
经典布局:
12列网格系统
grid-template-columns: repeat(12, 1fr)
杂志排版
grid-template-areas 定义区域
两栏式布局
只需要一行代码,左边栏设为70%,右边栏设为30%
1 | .wrapper { |
fr 实现等分响应式
fr 等分单位,可以将容器的可用空间分成想要的多个等分空间。利用这个特性,我们能够轻易实现一个等分响应式。grid-template-columns: 1fr 1fr 1fr
表示容器分为三等分
repeat + auto-fit——固定列宽,改变列数量
如grid-template-columns: repeat(auto-fit, 200px)
表示固定列宽为 200px,数量是自适应的,只要容纳得下,就会往上排列
1 | .wrapper { |
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
,表示这个网格项目跨度为3grid-auto-flow: row dense
表示尽可能填充,而不留空白
参考文章
这篇博客我结合了MDN web文档,B站视频,AI解答和以下博主的理解:
[1]本文参考了CSDN作者咸虾米_的grid布局文章
[2]本文参考了稀土掘金的grid布局文章稀土掘金
[3]这篇文章也很全面阮一峰-Grid 网格布局教程