CSS的排版方式大致上包括Table、Float、FlexBox和Grid四种。
Table
是属于最古老的方式, 目前已经很少有人使用。
Float
的排版方式曾经盛极一时,甚至用“DIV+CSS
”去形容当时的这种新颖的排版方式,而FlexBox
和Grid
则是真正为了页面布局而设计的排版方式。
FlexBox与 Grid的区别
最大的不同就是:
FlexBox
是属于一维的排版方式:一个FlexBox
容器只能控制一个方向,即水平方向或者垂直方向,如果需要控制另一方向则需要再添加一层FlexBox
容器
Grid
是属于二维的排版方式: 而Grid
容器则可以一次控制两个方向,这样就可以直接定义容器内元素的位置了。
下面话不多说直接开始撸代码
首先创建一个Grid容器
Grid布局分为: display:grid
和display:inline-grid
,grid
下容器元素都是块级元素,而inline-grid
则是行内元素
下面我们创建一个容器并指定grid属性。
html代码:
<div id="ruler"></div><div id="grid-container"></div>
css代码:
body{
margin: 40px;
}
#ruler{
position: absolute;
top: 0;
left: 0;
width: 580px;
height: 580px;
background-image: url(https://codingstartup.com/assets/grid/grid-ruler.png);
background-size: 580px 580px;
}
#grid-container{
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
}
这样我们就得到一个带有标尺的grid
容器。图上标尺为背景图,是为了能更好的理解Grid
布局。
接下来我们再找标尺的定义将水平和垂直方向都分为5格,水平方向为column
,垂直方向是rows
设定grid-template-rows属性:定义每一行的行高
css代码
#grid-container{
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
grid-template-rows: 100px 100px 100px 100px 100px;
}
grid-template-rows
代表垂直方向的设定,设置5个100px
,中间使用空格隔开,这样我们垂直方向就会分割出5个高度为100px的空间。
设定grid-template-columns属性:定义每一列的列宽
css代码
#grid-container{
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
grid-template-rows: 100px 100px 100px 100px 100px;
grid-template-columns: 100px 100px 100px 100px 100px;
}
grid-template-columns
代表水平方向的设定,同样设置5个100px
,中间使用空格隔开,这样我们水平方向就会分割出5个宽度为100px的空间。
(1) repeat()函数
而有时候,重复写同样的值会非常的繁琐,尤其是网格较多的时候。这时,我们可以使用repeat()
函数,简化重复的值。上面的代码用repeat()改写如下。
#grid-container{
display: grid;
width: 500px;
height: 500px;
background-color: #eee;
grid-template-rows: repeat(5 100px);
grid-template-columns: repeat(5 100px);
}
repeat()
函数接受两个参数,第一个参数是重复的次数(上例代码为5),第二个参数是所要重复在值(上例代码为100px)。
repeat()
可以和正常的设定值混用,例如我们将一个容器的row分为5份,第1份为200px,其余每份为100px,这样可以大大提高灵活性。
grid-template-rows: 200px repeat(4 100px);
(2) auto-fill关键字
有时,网格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的网格,这时可以使用auto-fill
关键字表示自动填充。
grid-template-columns: repeat(auto-fill, 100px);
上面代码表示每列宽度100px,然后根据容器的宽度自动填充,知道容器不能放置更多的列。
(3) fr 关键字
为了方便表示比例关系,网格布局提供了fr关键字(fraction 的缩写,意为"片段")。有时,我们并不是所有的网格都要设置为绝对单位的,而是相对的,这时可以使用fr
关键字表示比例。1fr即占有一份的意思,如果将上面代码中的100px都改为1fr的话,即各占5分之1的空间。
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
fr
关键字可以和正常的设定值混用,例如我们将一个容器的row分为5份,第1份为200px,其余每份为1fr。这时容器会先将第1份空间设定为200px,再去把剩余的空间分为4份,平均分配。
grid-template-rows: 200px 1fr 1fr 1fr 1fr;
(4) minmax()
minmax()
函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
上面代码中, minmax(100px, 1fr)
表示列宽不小于100px, 不大于1fr
(5) auto 关键字
auto关键字
表示由浏览器自己决定长度。
grid-template-columns: 100px auto 100px;
上面代码中, 第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width
,且这个值大于最大宽度。
设定好grid容器之后,接下来我们就可以往里面添加一些元素了
添加元素
先在grid容器内添加两个div
盒子,并设置背景颜色
html代码
<div id="grid-container">
<div class="cell-1"></div>
<div class="cell-2"></div>
</div>
css代码
.cell-1{
background-color: blue;
}
.cell-2{
background-color: yellow;
}
现在我们可以看到蓝色和黄色各占一格,这是在未定义元素的位置时预设的情况。
如果我们想将蓝色占据左上方的4格,也就是占据标尺中row
的1-3和column
的1-3,我们可以这样设置:将grid-row
设置为1/3,grid-column
设置为1/3。
再将黄色占据左下方的4格,也就是占据标尺中row
的4-6和column
的4-6,我们可以这样设置:将grid-row
设置为4/6,grid-column
设置为1/3。
css代码
.cell-1{
background-color: blue;
grid-row: 1/3;
grid-column: 1/3;
}
.cell-2{
background-color: yellow;
grid-row: 4/6;
grid-column: 1/3;
}
这样蓝色和黄色元素已经占据了对应的位置了,而当我们要调整元素在grid
容器内的位置时只需要修改grid-row
和grid-colu
的值即可:例如将蓝色的grid-row
改为1/4,黄色的grid-column
改为2/6,则会变成下图的效果:
css代码
.cell-1{
background-color: blue;
grid-row: 1/4;
grid-column: 1/3;
}
.cell-2{
background-color: yellow;
grid-row: 4/6;
grid-column: 2/6;
}
为什么在上方我们会先定义grid
容器的row
再定义column
呢?原因在于grid-row
和grid-column
有一个简写的方法grid-area
grid-area属性
接下来我们用grid-area
属性去设定蓝色元素
css代码
.cell-1{
background-color: blue;
/* grid-row: 1/4; */
/* grid-column: 1/3; */
/* 以上两行代码可以简写为以下一行代码 */
grid-area: 1/1/4/3;
}
可以看到效果都是一样的,grid-area
的设置顺序是:grid-row
的第一个值、grid-column
的第一个值、grid-row
的第二个值、grid-column
的第二个值,也可以理解为‘坐标’,即左上角、右下角坐标
。
那么这个方法纯粹是为了介绍给大家知道具体是使用哪种属性因人而异,因为个人觉得grid-area
的设定值不是很直观。
那么现在grid-row
和grid-column
的设定值是由第几至第几
的意思,例如由第1至第3:1/3
但是我们在实际开发中布局的时候并不会像现在这样有一把标尺,让我们能一眼就看出来对应的数字,所以它还有一种写法是由第几开始延伸多少格
,通过span
关键字,span
就是延伸的意思,例如蓝色元素的grid-column
可以改写为:
css代码
.cell-1{
background-color: blue;
grid-row: 1/4;
grid-column: 2/ span 3;
}
如果需要设置单元格之间的间隔则需要用到一下的属性。
grid-row-gap属性,grid-colunm-gap属性,grid-gap 属性
grid-row-gap
属性设置行与行的间隔(行间距),grid-column-gap
属性设置列与列的间隔(列间距)。
#grid-container {
grid-row-gap: 20px;
grid-column-gap: 20px;
}
这样我们每个单元格之间都会有20px的间隔。
grid-gap
属性是grid-column-gap
和grid-row-gap
的合并简写形式,语法如下。
grid-gap: <grid-row-gap> <grid-column-gap>; 第一个参数是行, 第二个参数是列
所以我们上面的css代码可以简写成:
#grid-container {
grid-gap: 20px;
}
而如果grid-gap
省略了第二个值,浏览器认为第二个值等于第一个值。
根据最新标准,上面三个属性名的grid-前缀已经删除,
grid-column-gap和grid-row-gap写成column-gap和row-gap,grid-gap写成gap。
grid-template-areas 属性
网格布局允许指定"区域"(area),一个区域由单个或多个单元格组成。grid-template-areas
属性用于定义区域。
#grid-container { display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 300px 100px;
grid-template-areas: 'h h h'
'n m m'
'f f f';
}
.head { background-color: rgb(248, 35, 35); grid-area: h}.nav { background-color: rgb(253, 253, 24); grid-area: n}.main { background-color: rgb(70, 70, 243); grid-area: m}.footer { background-color: rgb(77, 250, 86); grid-area: f}
通过配置区域, 我们可以快速搭建出一个经典的页面布局
grid-auto-flow 属性
划分网格以后,容器的子元素会按照顺序,自动放置在每一个网格。默认的放置顺序是"先行后列",即先填满第一行,再开始放入第二行,即下图数字的顺序。
这个顺序由grid-auto-flow
属性决定,默认值是row
,即"先行后列"。也可以将它设成column
,变成"先列后行"。
#grid-container { display: grid; background-color: #999; grid-template-rows: 100px 100px 100px; grid-template-columns: 100px 100px 100px; grid-gap: 5px; grid-auto-flow: column;}
上面代码将grid-auto-flow
设置为columu
以后,顺序就变成下图数字的顺序
justify-items 属性,align-items 属性,place-items 属性
justify-items
属性设置单元格内容的水平位置(左中右),align-items
属性设置单元格内容的垂直位置(上中下)。
这两个属性的写法完全相同,都可以取下面这些值。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
#grid-container { display: grid; width: 310px; background-color: #999; grid-template-rows: 100px 100px 100px; grid-template-columns: 100px 100px 100px; grid-gap: 5px; grid-auto-flow: column; justify-items: center;}
设置了justify-items: center;
就如上图所示。
place-items
属性是align-items
属性和justify-items
属性的合并简写形式。
place-items: <align-items> <justify-items>; 第一个参数是垂直, 第二个参数是水平
下面设置一下place-items: start start; 就如下图所示。
如果省略第二个值,则浏览器认为与第一个值相等。
justify-content 属性,align-content 属性,place-content 属性
justify-content
属性是整个内容区域在容器里面的水平位置(左中右),align-content
属性是整个内容区域的垂直位置(上中下)。
这两个属性的写法完全相同,都可以取下面这些值。(下面的图都以justify-content
属性为例,align-content
属性的图完全一样,只是将水平方向改成垂直方向。)
- start - 对齐容器的起始边框。 默认值
- end - 对齐容器的结束边框。
- center - 容器内部居中。
- stretch - 项目大小没有指定时,拉伸占据整个网格容器。
- space-around - 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
- space-between - 项目与项目的间隔相等,项目与容器边框之间没有间隔。
- space-evenly - 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
place-content
属性是align-content
属性和justify-content
属性的合并简写形式。
place-content: <align-content> <justify-content> 第一个参数垂直, 第二个参数水平
place-content: space-around space-evenly;
如果省略第二个值,浏览器就会假定第二个值等于第一个值。
justify-self 属性,align-self 属性,place-self 属性
justify-self
属性设置单元格内容的水平位置(左中右),跟justify-items
属性的用法完全一致,但只作用于单个项目。
align-self
属性设置单元格内容的垂直位置(上中下),跟align-items
属性的用法完全一致,也是只作用于单个项目。
这两个属性都可以取下面四个值。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
下面是justify-self: start;
place-self: center center 的例子。
.cell-1 { text-align: center; font-size: 28px; justify-self: start; background-color: rgb(248, 35, 35);}.cell-2 { text-align: center; font-size: 28px; place-self: center center; background-color: rgb(253, 253, 24);}
place-self
属性是align-self
属性和justify-self
属性的合并简写形式。
place-self: <align-self> <justify-self>;
如果省略第二个值,place-self
属性会认为这两个值相等。
本文引用资料:
1. www.bilibili.com/video/BV1XE…
2. www.ruanyifeng.com/blog/2019/0…