回顾一下web
页面布局的历程,于我个人而言,经历了最开始的学习计算机编程时的table
布局和基础的div+css
布局,再到后来的flex
弹性盒布局。div+css
布局给web
页面布局带来了更多可能,解决了table
布局的局限性。页面是以代码的自上而下的文档流的形式呈现的,所以div+css
的浮动解决了横向布局的问题。再后来css3
提供了flex
布局的特性,让横向布局特别是移动端布局变得更加容易。
本文主要来说说与flex
布局类似的grid
布局。flex
给我们带来了“轴线”的概念,相当于是“一维”的,而grid
布局则是将容器分成了“行”和“列”,可以说是“二维”的。
老规矩,只说干货,开整。
首先,我们的基本结构如下:
* {
margin: 0;
padding: 0;
list-style: none;
}
.container {
width: 700px;
height: 700px;
background-color: #efefef;
margin: 20px auto;
display: grid;
}
.item {
width: 100px;
height: 100px;
line-height: 100px;
font-size: 30px;
font-weight: 500;
text-align: center;
}
.item:nth-child(2n) {
background-color: pink;
}
.item:nth-child(2n + 1) {
background-color: yellow;
}
<div class="container">
<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>
一、display: grid属性
先给父容器加上display: grid
看看效果:
二、单元格
此时,通过检查元素可以发现,给父容器声明grid布局之后,容器根据内容自动分割成了6行()。到这儿,我突然明白了什么…grid不同于flex的“轴”的概念,所以发现此时虽然已经设置了父容器为grid,但是容器内的元素仍然是流式排列。既然此处有了行,那么应该也会有列的概念,以及该如何设置行和列的宽度和位置的问题。
可以通过grid-template-rows: 120px 120px 120px 120px 120px 120px;
设置每一行的宽度,然后通过设置grid-template-columns: 120px 120px 120px 120px 120px 120px;
来改变列的宽度。此时,页面样式变成了这样:
由行和列组成的区域我们把他称为单元格。刚才说到了grid-template-rows
和grid-template-columns
属性,像刚才那种情况可以用repeat
函数简写,repeat
接收两个参数,第一个参数是要重复的次数,第二个参数是要重复的值,基本示例如下:
.container {
display: grid;
grid-tempalte-rows: repeat(6, 120px);
grid-tempalte-columns: repeat(6, 120px);
}
repeat
的第一个参数还有一个固定值auto-fill
:
.container {
display: grid;
grid-tempalte-columns: repeat(auto-fill, 120px);
}
顾名思义,这个auto-fill
的意思就是用120px的列来填充容器,直至填满为止。
- 同时,这个你也可以是用百分比的数值:
.container {
display: grid;
grid-tempalte-columns: repeat(auto-fill, 15%);
}
fr
关键字
示例代码:
.container {
display: grid;
grid-tempalte-columns: 1fr 2fr;
}
页面效果:
fr
是fraction
(意为部分、片段)的缩写,1fr代表占据父容器rows
的fr
总和的一份。写到这儿我想到了那道经典的css
布局问题:如何实现左侧固定宽度,右侧宽度自适应?(类似于后台管理系统的左侧菜单固定宽度,右侧内容区域宽度自适应的效果)。如果用grid
布局来做的就很简单:
.container {
display: grid;
grid-tempalte-columns: 200px 1fr;
}
另外值得注意的是display: grid
之后的容器仍然是块级元素,如果需要行内块元素的话,使用display: inline-grid
即可,这一点和flex布局是一样的。
三、网格线
单元格的相邻区域称为网格线,示意图如下:
- 可以通过
grid-row-gap
和grid-column-gap
属性来设置网格线的间隙:
示例代码
页面效果.container { display: grid; grid-template-rows: 120px 120px 120px; grid-template-columns: 120px 120px 120px; grid-row-gap: 20px; grid-column-gap: 20px; }
四、内容在单元格中的位置
设想一种情况,如果单元格的宽高大于单元格内内容的宽高,那么该如何去设置内容在单元格中的内容呢?此处引入justify-items
属性和align-items
属性。 熟悉flex
布局同学应该都知道这个,但是在grid
布局中有些许区别。
示例代码:
.container {
background-color: #efefef;
margin: 20px auto;
display: grid;
grid-template-rows: 120px 120px 120px;
grid-template-columns: 120px 120px 120px;
align-items: center;
justify-items: center;
}
页面效果:
这样单元格里的内容就在单元格中居中了,这两个属性的写法完全相同,都可以取下面这些值。
start:对齐单元格的起始边缘。
end:对齐单元格的结束边缘。
center:单元格内部居中。
stretch:拉伸,占满单元格的整个宽度(默认值)。
和flex
类似,grid
也可以使用justify-content
和align-content
属性来控制内容在容器中的位置,属性值和用法与flex
类似,此处不再赘述。
哦~对了,顺便提一嘴grid
的兼容性,据我个人平时观察还是有不少项目在使用的,在caniuse上查询了一下浏览器的支持情况,如下: