grid布局就是表格布局(grid layout),或者称之为栅格布局也行。因为栅格布局的概念来自于bootstrap,这里使用栅格布局来与bootstrap做关联,是因为它俩是描述的同一个东西。自从有了CSS3原生表格布局,想象一下,以前用样式框架在一行中添加很多属性,无形中增加了几倍代码,grid布局就用几行代码就完成了框架很多配置才完成的功能,这是多美的一个进步。网格布局的属性相当多,有很多一个属性代表了另外两个属性的综合体。
grid布局可以完全替代flex布局,但是得先熟练,熟练的前提是会用,用的前提是得了解网格布局是什么。
目录
环境说明
- 本文渲染图均取自于Firefox 80.0 (64 位)浏览器
- 本文编码运行于以下浏览器均无异常
-
Microsoft Edge 85.0.564.68(Chromium内核)
-
Firefox 81.0.1
-
- 代码编辑于windows 10 19041.508
- 本文编码器及其版本:vscode 1.49.1
- 本文涉及使用flex布局
- 自文章发布后,2020年10月6日重写过文章内容顺序,使其易于理解
参考链接
属性简介
1、作用于容器的属性
gird-template-areas
:用于分配区域名称,然后元素使用grid-area
指定占用某一区域,完成区域分配grid-template-columns
:用于定义网格(表格)列相关属性。如定义列线名称,列宽,定义多少列grid-template-rows
:用于定义网格(表格)行相关属性。如定义行线名、行高、定义多少行grid-auto-columns
:定义在grid-template-columns
与grid-template-rows
区域之外的列宽。也就是单元格在超出容器规定区域时,定义其列宽。在容器内的元素超过预定义的区域以后,或与grid-column
配合使用时可出现效果grid-auto-rows
:定义在grid-template-column
s与grid-template-rows
区域之外的行高。同grid-auto-columns
类似,当单元格超出规定区域时,定义其行高。grid-auto-flow
:用于定义单元格的排列方向,同时可附加饱和填充配置column-gap
:定义容器中被单元格组成的列之间的间隙,简称列间隙row-gap
:定义单元格行之间的间隙,或者说叫相邻单元格的间隙gap(旧名grid-gap)
:是一个column-gap
与row-gap
复合属性,第一个值为row-gap
的取值范围,第二个值为colum-gap
的取值范围justify-items
:用于对单元格内容的水平对齐方式align-items
:用于定义单元格内垂直对齐方式place-items
:justify-items与align-items复合属性,第一个值为align-items的取值,第二个值为justify-items取值justify-content
:用于定义由单元格组成的列之间的间距,简称列间距align-content
:用于定义由单元组成的行之间的间距,简称行间距place-content
:一个由justify-content
与align-content
组合而成的复合属性。第一个值为align-contetn的取值范围,第二个值为justify-content的取值范围。grid-template*
:grid-template-rows
、gird-template-columns
、grid-template-areas
的复合属性,本文不做介绍
2、作用于元素的属性
grid-area
:指定区域的名称,需要配合grid-template-areas
使用grid-column-star
:合并同一行单元格时,起始单元格的左列线名grid-column-end
:合并同一行单元格时,结束单元格的右列线名grid-column
:grid-column-star
与grid-column-end
的复合属性,第一值为grid-column-start
的取值,第二个值为grid-column-end
取值,两值之间需要添加/
符号:gird-column-start / grid-column-end
,在两值之间的区域会被合并为一个单元格。grid-row-star
:合并同一列单元格时,起始单元格的上横线名grid-row-end
:合并同一列单元格时,结束单元格的下横线名grid-row
:gird-row-start
与grid-row-end
复合属性,第一个值为grid-row-start
的取值,第二个值为grid-row-end
的取值,两值之间需要加上/
符号:grid-row-start / grid-row-end
justify-self
:在父元素(容器)设置了justify-item
的基础之上,如果子元素需要自定义自身在单元格中的水平对齐方式,需要使用到的元素align-self
:在父元素(容器)设置了align-item
的基础上,如果子元素需要自定义自身在单元格中的垂直对齐方式,需要使用到这个属性
一、网格布局理念
1.1 网格的形成
一个网格的形成,需要由一些列线和横线相互之间垂直交错,才能形成一个网格。在后文中这些列线和横线都可以有各自的名字1,在规划元素占用哪些范围网格时,会使用到这些横线和列线。
对于如何划分区域,是按比例划分列?还是按照每一个单元格划分多少像素,还是按每个单元格容纳多少字符计算?这都由开发者本人根据当时情况来决定,自由度是很不错的。
1.2 网格布局的优势
传统意义上,使用table标签结合th tr td标签,划分出来的表格,时常难以维护,因为被划分出来的表格都将是写死了的,没有灵活性可言。例如,我想要将原来30 * 10
的网格,修改为15 * 20
的表格特,要对原有的html标签内容做不少的修改,是一个相当麻烦的事。有了grid布局,不再需要修改html,只需要修改几行样式配置(css),即可改变表格的结构,而不用像table标签布局那样,去修改大量的html标签。更加值得注意的是,grid布局对标签的依赖性不高,如果按照表格系列标签来做网格布局的话,是做不到换行操作的,怎么都需要借助js进行dom操作。但grid布局对元素换行行为,就不再依赖于js操作2,使用纯css都可以实现以前基于框架才有的动态效果,所以这就是很香!
二、对容器划分表格
本文需要通过实例演示具体样式,所以要先贴出本文基础代码,在介绍样式属性时,再根据基础代码修改,以此避免读者不理解的情况发生。在基本代码中,对容器的样式属性中尤其要注意display设置,因为本文中所有的样式,都是要根据这个display属性是否取值gird或inline-gird。其中inline-grid表现容器在外部环境中是否使用行内样式,也就是说,容器可以自定义自己在外部(父元素)环境中是否属于行内元素。
0、基本代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
}
[class^=item]{
box-sizing: border-box;
background-color: blueviolet;
display: flex;
align-items: center;
justify-content: center;
border-width: 1px ;
border-style: solid;
border-color: aquamarine;
color: white;
}
</style>
</head>
<body>
<div id="con">
<div class="item1">item1</div>
<div class="item2">item2</div>
<div class="item3">item3</div>
<div class="item4">item4</div>
<div class="item5">item5</div>
<div class="item6">item6</div>
<div class="item7">item7</div>
<div class="item8">item8</div>
<div class="item9">item9</div>
<div class="item10">item10</div>
</div>
</body>
</html>
初始渲染样式如下:
1 、 grid-template-column:对容器分列(划分容器重要属性)
对于表格布局,对区域的划分,一定由列线和行线构成,这里先介绍分列。grid-template-column的值是一个由空格分隔的值,每一个被空格分开的值都代表一列的列宽。在后文中也可以理解为占用容器总宽度的比列。
1.1 使用像素(pixel)分列
假设容器需要被设置成3列,第一列的宽度为200像素(pixel),第二列和第三列要被划分为100像素,那么对grid-template-column的配置可以这么写:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 200px 100px 100px;
}
渲染样式如下:
通过浏览器开发者模式,可以知道在item1所在的列,单元格的宽度都是200像素,而item2和item3所在的,宽度都是100像素。因为在前文中说明,grid-template-columns中,每一个由空格分开的值,都代表一列的宽度,在这里只写了三列宽度,那么容器就只被划分了三列。这里出现了自动换行,这是因为grid-auto-rows的缘故,在后文会有介绍。
1.2 使用百分比分列
如果使用像素位划分列的话,那就等于将宽度固定了,如果容器宽度发生变化,那就会发生样式错位了,显然不够灵活。为了解决这个可能的错误,可以使用百分比来表示各列宽度。这里得提醒一下,如果各列的百分比总和大于1的时候,那么容器宽度怎么调,里面的元素都撑破容器跑到外面去,这个情况就不太好了。
所以在使用百分比的时候,一定要注意各列的百分比之和要小于等于1(100%)。
例如,我们要将一个容器分为4列,每一列占用容器的25%。css可以这样写:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 25% 25% 25% 25% ;
}
渲染效果如下:
代码解释
:以上css配置中,grid-template-columns的值有四个,这代表容器被分为了4列。这四个值都是25%,这代表这四列宽度都是占容器宽度的25%。这样,不论窗口怎样变化,容器里面的每一列,都会随着变化改变自身大小,那么使用固定像素值作为列宽,可能出现问题就不存在啦。
1.3 分列单位3:fr
在使用百分比的时候,通常需要去计算百分比的值,例如,我要将第一列、第二列与第三列的比例划分为1:2:3,且三列之和等于容器宽度。这个时候去计算百分比的值,就显得非常麻烦,而且百分比值还不一定完美。因此,对列的划分就引入了一个新的比例单位fr,将具体数值交给程序自动处理,省去了计算百分比的麻烦。
例如 grid-template-column:1fr 2fr 3fr;就表示:这个容器被分为三列,因为属性值有三个个:1fr 2fr 3fr,第一列、第二列与第三列的比值为1:2:3。来看看示例吧:
css配置如下:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 1fr 2fr 3fr;
}
配置效果渲染图如下:
代码解释
:通过以上css样式配置以及效果图来看,id为con的容器,将其内部分为了三个列:他们的比例关系为1:2:3,且各列的宽度之和等于容器的宽度。
1.4 分列单位4:ch
这个单元用于表示分列时,一列的宽度以字符为单位进行分列,比如,grid-template-columns:2ch 3ch就表示,第一列2字符宽度,第二列3字符宽度,当然,所谓的字符宽度时以英文字符为单位的。
1.4 自动填充:auto与宽度分配优先级
在使用固定像素位、百分比都有可能会存在宽度有剩余的情况。这个时候,如何如处理剩余的宽度,或者怎样精确的分配剩余容器宽度,这个使用auto再合适不过了。
例如,我们要将一个盒子第一列分配30%的容器宽度,第三列分配100px(100像素)容器宽度,剩下的不管多少空间,统统给予第二列。这个时候因为使用的混合分配,使用百分比也不可能计算剩下宽度,使用固定值也无法满足剩下宽度。所以使用auto分配剩余空间最合适。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 30% auto 100px;
}
效果图如下:
auto在grid-template-columns中等于一列的占位符。类似于1fr,但是区别于fr。在下文我将展示这个区别。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 30% 1fr auto;
}
渲染效果:
我在上文介绍的所有分列单位中,各个单位都可以混合使用,但总是在使用百分比和固定像素值的列满足之后,再满足auto列的基本宽度需求,最后再利用剩余宽度给以fr为单位的列。
1.5* 给列线命名
在上文已经通过示例如何对列宽分配,但是却没有说列线。队列线的概念,我在文章开始的时候,就说明了它的存在,但是放到现在才说,是因为使用到列线,就需要涉及到容器的子项配置。需要配合对容器子项的属性grid-column-start grid-column-end grid-column,在此时提及,不太合适。但还时来来简单介绍一下。给列线命名还是使用grid-template-columns属性。格式如下:[col-line-name] col-width [col-line-name] col-width [col-line-name] …
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: [col1] 30% [col2] 1fr [col3] auto [col4];
}
代码解释
:代码中中括号中的内容就是列线名,col1就是对第一列左列线命名,col2就是对第一列右列线的命名,col2同时也是第二列的左列线名。因为通过浏览器开发者模式也无法看出来,所以这里就不再贴出效果图了
2、grid-template-rows:对容器分行(划分容器重要属性)
grid-template-rows用于对容器的分行,分行属性的使用方法和分列的方法是一样的用法。
这里值得注意的是,在上文分列的时候,并没有给容器指定划分多少行,但是容器为配置自动分行了。
按照现在既有代码来分析的话。我在代码中指定了每一行有3个元素,那么按照表格布局的模式,我还要给容器划分4行,才能算得上表格布局。
上文中,等于是容器自动检测到内部具有10个元素,然后根据每一行3个元素,算出,至少需要4行,才能容纳所有的元素,且每一行等比例的占满容器高度——也就是说,4行平分容器高度,作为每一行的行高。
这就是容器的默认分行方式,其实默认的分行方式都还算不错啦。但是,总有需要自定义分行的时候嘛。
2.1 使用像素分行
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 50px 50px 100px 50px;
}
效果图如下:
代码解释
:以上代码表示,容器一共被分为4行,第一行、第二行、第四行都是50px(像素位),第三行是100像素宽度。
2.2 使用百分比分行
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 25% 25% 10% 20%;
}
代码解释
:表示一共分为4行,第一二行为容器总高度的25%,第三行为容器总行高10%,第四行为容器总行高的20%。
2.3 使用fr分行
这里就是使用等比占用,且各行的高度之和等于容器高度。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 2fr 1fr 1fr;
}
代码解释
:以上配置中,第一行、第二行、第三行与第四行的之间的比例关系是:1:2:1:1,且他们总高度之和等于容器高度。
*2.4 隐藏在分行中的auto
在上文分行中,每一类分行我都是分的四行。如果尝试将3*3
的网格划分容器的话,结果可能会出乎意料,因为本身按照3*4
划分才能容得下所有元素,划分到3*3
容器中,将会有一个多余的元素。请看实例:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 2fr 1fr;
}
很显然,分列时,同时使用fr与auto分列时,也有相似的情况。这里分行时先是按照最低高度给auto列分高,然后利用剩下的高度给所有使用fr高度的行,按比例划分剩下容器高度。
也就是说,不在容器规划范围内的行,容器默认给予其auto分行的方式,我们可以做一个示例来验证一下,这和分列的遇到fr单位与auto混合使用的时时一样的:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: [col1] 30% [col2] 1fr [col3] auto [col4];
grid-template-rows: 20% 100px 10% auto;
}
grid-template-columns按照空格划分,每一个被空格隔开的值,都是代表一列的宽度或者占总宽度的比例;
同样,grid-template-rows也一样,每一个通过空格隔开的值,都代表一行的宽度或者占容器总高的比例
3、函数minmax()
有关参考链接:css minmax()函数介绍
这个一个辅助函数,给容器中的一列或者一行划分最小宽度和最大宽度或者最小高度和最大高度的,也就是说,当某一列或者某一行宽度不够或者高度不够时,某一列或某一行还能保持最低宽度或最低高度。使用这个函数,跟我们定义一行或者一列一样,使用方式并没有什么不同。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: minmax(200px ,1fr) minmax(200px,1fr) 1fr ;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
效果图如下:
代码解释
:从上图看起来,第一列和第二列的最小宽度都是200px,而他们的最大宽度时1fr,已经触及到最小宽度了,所以第一列和第二列不会缩小,相反,第三列因为没有最小宽度限制,已经被压缩啦。
换一种角度来思考:
现在css样式时这样的:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: minmax(100px ,1fr) minmax(100px,1fr) 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}
效果图如下:
上图看起来和grid-template-columns:1fr 1fr 1fr;没有什么区别,原因在于每一列的最大宽度,就是各列平分容器宽度的样子。
但是当容器变小时,就会有变化啦,例如,容器缩小到240px时,因为容器的缩小,如果按原来平均分的话,每一列都只有80px,所以不满足一二列的最低100px,所以就会优先满足有最低宽度为100px的一二列,没有底线的第三列,就没法了,必须做出让步。所以当容器缩小时,就会先满足前两列的最低需求,然后缩减第三列,以达到配置要求。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 260px;
height: 400px;
display: grid;
grid-template-columns: minmax(100px ,1fr) minmax(100px,1fr) 1fr ;
grid-template-rows: 20% 100px 10% ;
}
效果图如下。
除了列以外,分行时的对行高的限制也可以使用这个函数。这里就不再做演示了。
4、grid-auto-rows:分配默认行高
使用这个属性的时机,在对容器的网格划分无法容纳所有元素时,元素默认会向下扩充,此时,扩充的行行高因该是多少,就由这个属性决定。
例如,在本文代码中,我在容器内规定了十个元素,如果我在划分容器的时候,只给予3*3宽度,按照上面的逻辑,第十个元素会向下扩充一行,这时,如何规定第四行的高度,这个(grid-auto-rows)属性就排上了用场。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px; /* 注意这里被修改回500像素了 */
height: 400px;
display: grid;
grid-template-columns: minmax(100px ,1fr) minmax(100px,1fr) 1fr ;
grid-template-rows: 1fr 1fr 1fr;
grid-auto-rows: 1fr
}
渲染结果图
代码解释:以上css配置,同没有配置样式属性grid-template的网格渲染样式一致。说明一件事,grid-auto-rows默认值是等于1fr的,这样才能达到同样的效果,在以上css配置中取消grid-template-rows,你将看到一摸一样的效果。
5、grid-auto-columns:分配默认列宽
这个属性是在分配的列不够时,给予超出的列一个默认的宽度。当然,正常情况下,列数不够的时候,元素默认会向下排列,根本不可能存在列数不够的情况。对于这个属性的使用需要结合用于子选项上的grid-column-start、grid-column-end或grid-column才行,在后文介绍这三个属性的时候,在来介绍这个属性。
6、函数repeat():重复分列/分行模式
在上面的代码中,不知道读者有没有一点点想法,如果容器或者屏幕足够大,我要划分的网格比较多,但是表格又都是同等大小的,这个时候要写不少对列或行一样的定义,比如我要写10 * 10的表格,那不得写20个1fr吗?这个时候就可以用css函数repeat捡个懒。
例如要划分10列等比的网格列。那么我就给grid-template-columns属性的值使用,repeat函数代替。只需要将repeat函数的第一个参数传入10,第二个参数传入1fr。第一个参数代表重复次数,第二个参数就是要重复的样板。
基于本文的代码,我在这里给容器划分4列3行的表格:
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(3,1fr);
}
代码解释:根据以上css渲染图以及配置。可以知道repeat参数中第一个参数就是代表需要重复模式,而第二个也许还不能够说明什么是重复模式,或者叫模板。
我这里举个例子:我要对容器列重复一种模式填充满容器,例如,开始的第一列是100像素,紧接着第二列为1fr,然后紧接着第三列是2fr。再后面就是重复第一列的100像素,然后重复1fr,然后重复2fr。这样一共就划分了6列。但可以看出规律来,也就是对列的划分按照100px 1fr 2fr重复两次,所以像100px 1fr 2fr 这样就可以称之为模式,或者叫模板。使用repeat函数表达如下。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(2,100px 1fr 2fr);
}
代码解释:通过以上代码,以及显示效果来看,名称为1的列线到名称为4的列线之间于4号列线到7好列线之间的模式就是一样的:100px 1fr 2fr,他们都重复了2次。不过这里显示很像100px 50px 100ox的格式,是因为在给容器分配表格的时候,一般会优先满足使用固定像素位和使用百分比列或行。将剩下宽度或者高度,按照比例关系分配给使用fr为单位的列或行。所以根据这个原则计算上面的渲染图。就是500宽度-200被占用的固定宽度。给予以fr为单位的列,那么他们比例关系为1:2:1:2,共6份,每一份50就是50像素,所以每一个模式中占用1fr的列实际宽度为50px,占用2fr的宽度为100px。因此我们在渲染图中可以见到,同一模式中的第一列和第三列是一样的宽度。
repeat与响应式
有关参考链接:css repeat函数详细介绍
repeat第一个参数除了是数字以外,还可以是auto-fill、auto-fit,结合minmax()函数使用,可以发挥更加强大的布局样式。
7*、grid-auto-flow:定义行扩充方向
默认情况下,容器使用网格布局的时候,其内部的元素默认的排列方向,总是先从左往右,再自上而下排列元素。但还可以规定先自上而下,再自左向右排列。总的来说grid布局,就只有这两种布局方式了,比不上flex布局有2 * 4
种排列方式。这里简单介绍一下该样式属性即可。
#con{
background-color: bisque;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(4,1fr);
grid-auto-flow: column;
}
代码解释:可以看到,使用grid-auto-flow先满足自上而下的列排列好,再向右扩充列。
这个属性除了能改变行的扩充方向以外,还可以有其他的作用,这个将在后文,介绍于子元素属性的时候再做介绍。
三、合并单元格
合并单元格是个特殊操作,当对容器不满足于网格形式布局形式的时候,例如,要一个容器单元格占两格单元格的时候。就需要使用到单元格合并,以满足对容器网格的特殊划分,例如我要在头部使用四个单元格划为一行,用来当作论坛的头部一级菜单。我要在最左边划分一列,共占用3行作为网站的二级菜单。其他部分作为网站内容主体,就如下图所示的区域划分,使用grid布局就很容易实现,事实上,该图例也是使用grid来实现的。
其剖析图如下:
如果要使用单元格合并,那么必须要规定子单元格如何合并,从什么位置到什么位置合并为当前单元格。所以本质上,本节介绍的属性是写在子元素上的,由子元素来决定,自己如何占用容器所划分的单元格。
在grid布局中,对单元格的合并,需要使用到分隔线,包括分隔行的行线,分隔列的列线,都是分隔线。在指定合并哪些单元格时,就是在指定哪两个分隔线之间的范围——或者说元素想占用哪个分割线到哪个分割线之间的范围。
因为下文中,使用不到太多的单元格,所以新的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(4,1fr);
}
[class^=item]{
box-sizing: border-box;
background-color: blueviolet;
display: flex;
align-items: center;
justify-content: center;
border-width: 1px ;
border-style: solid;
border-color: aquamarine;
color: white;
}
.item1{
background-color: teal;
}
.item2{
background-color: tomato;
}
</style>
</head>
<body>
<div id="con">
<div class="item1">item1</div>
<div class="item2">item2</div>
<div class="item3">item3</div>
<div class="item4">item4</div>
<div class="item5">item5</div>
<div class="item6">item6</div>
</div>
</body>
</html>
初始渲染样式如下:
1、grid-column-start、grid-column-end与grid-column合并列
grid-column-start代表要某元素要占用列线的起点列线索引。而grid-column-end表示元素要占用范围的结束列线索引。例如,我要第一个元素,占用容器的第二根列线到最后一根列线之间的范围。所以,class为item1的元素样式如下:
.item1{
background-color: teal;
grid-column-start: 2;
grid-column-end: 5;
}
代码解释
:如上图所示,使用css将第一个元素将第二根列线,到第五根列线之间的范围成功合并,但是分割线索引如何知道呢?
解析图如下,每一个箭头直线的都是一根分割线,箭头上的数字就是分隔线的索引(取自Firefox浏览器开发者模式)
place-column是grid-column-start与grid-column-end复合属性,该属性可以使个格式:开始列线索引/结束列线索引
,表示合并的区域范围。例如下列css配置将于上图一致:
.item1{
background-color: teal;
/* grid-column-start: 2;
grid-column-end: 5; */
grid-column: 2/5;
}
2、再谈grid-auto-flow:容器的饱和填充
通过以上样式,可能你已经发现了,那第一个单元格空了,这应该怎么解决。这种发生单元格空缺的情况,只有再合并单元格才会出现。也就是按照正常文档流排列顺序时,当剩下的空余不足以后面一个元素时(此处描述有误),那么如何安排剩余空间,使容器能够填满。这个时候要使用grid-auto-flow的第二类值:dense,表示容器的填充方式是否饱和填充。当然这个属性也可以有两个值,但是要用空格分开。例如使用这个属性规定排列优先满足列填充,然后还要饱和填充。总之,你只需要记住grid-auto-flow可以设置排列方式和饱和时填充容器这两个功能就好了。
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(4,1fr);
grid-auto-flow: dense;
}
3、grid-row-start、grid-row-end与grid-row:合并行
grid-row-start代表要合并范围的起始行分割线索引,grid-row-end表示合并范围的结束行线索引,例如,我要将第二个元素合并到第三行。那么就是说class等于item2的元素,要将第一根行线,到第四根行线之间的范围合并为一个区域,可以这么写(对容器grid-auto-flow样式有修改)
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(4,1fr);
grid-auto-flow: dense;
}
/*中间省略*/
.item2{
background-color: tomato;
grid-row-start: 1;
grid-row-end:4;
}
place-row是grid-row-start与grid-row-row-end的复合属性,使用格式:开始行线索引/结束行线索引
,下列css将与上图渲染图一致。
.item2{
background-color: tomato;
/* grid-row-start: 1;
grid-row-end: 4; */
grid-row: 1/4;
}
四、设置单元格之间的间隙
设置单元格间隙可能会使用到三个属性:row-gap、column-gap与gap。这三个属性用于设置单元格之间的间隙距离。不过row-gap值针对于行之间的间隙,而column-gap是针对于列之间的间隙。而gap是row-gap与column-gap的复合属性。
1、row-gap:单元格上下间隙
row-gap用于设置单元格上下之间的间隙,注意,是单元格之间,并不包括单元格与容器之间,所以我在容器内取消padding的值,以表现出来。
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(4,1fr);
grid-auto-flow: dense;
row-gap: 1rem;
}
2、column-gap:单元格左右间隙
这个属性用于设置单元格左右之间的间隙,注意,是单元格之间。
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(4,1fr);
grid-auto-flow: dense;
row-gap: 1rem;
column-gap: 2rem;
}
渲染图
透视图
以上代码中,我添加了对列之间的间隔配置,列之间为2rem,见渲染图可知。
3、gap单元格间隙
如果在样式中,需要同时对行之间与列之间的单元格间隙做设置,那么只需要gap一个属性就好了。gap的值是由空格分隔的两个值构成的,第一个值,也就是空格前面的那个值,代表行之间的间隔,第二个值代表列之间的间隔。下面这样的css配置将与上面的渲染图一摸一样。
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
padding: 1rem;
display: grid;
grid-template-columns: repeat(4,1fr);
grid-template-rows: repeat(4,1fr);
grid-auto-flow: dense;
/* row-gap: 1rem;
column-gap: 2rem; */
gap:1rem 2rem
}
五、设置元素在单元格内的对齐方式
划分的区域内,元素应该如何在单元格内对齐,可能需要的属性:align-items、justify-items或place-items。新的样式及html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(2,1fr);
}
[class^=item]{
box-sizing: border-box;
background-color: blueviolet;
display: flex;
align-items: center;
justify-content: center;
border-width: 1px ;
border-style: solid;
border-color: aquamarine;
color: white;
}
</style>
</head>
<body>
<div id="con">
<div class="item1">item1</div>
<div class="item2">item2</div>
<div class="item3">item3</div>
<div class="item4">item4</div>
<div class="item5">item5</div>
<div class="item6">item6</div>
</div>
</body>
</html>
1、align-items:单元格内垂直对齐方式
我要将容器内所有的单元格内容直居中对齐,可以这么配置:align-item:center
:
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(2,1fr);
align-items: center;
}
解析图
2、justify-items:单元格内水平对齐方式
设置容器内所有单元格内容的水平对齐方式,使用justify-items。例如我要将单元格的内容,再水平方向上右对齐,可以这么写:justify-items:end
:
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(2,1fr);
align-items: center;
justify-items: end;
}
透视图
3、place-items:align-items与justify-items复合属性
而使用place-item可以同时设置单元格内的元素垂直和水品对齐方式,它的值由空格分开的参数构成,空格前面的代表垂直对齐方式,空格后面的代表水平对齐方式,以下css配置将和上图一致:
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows: repeat(2,1fr);
/* align-items: center;
justify-items: end; */
place-items: center end;
}
六、元素自定义在单元格中的对齐方式
在上一节介绍了,对容器内所有单元格内容的对齐方式以后,总会有些情况需要对单元格内容的特殊设置。因为是自身要脱离容器的全局样式,那么,要自定义的话就是元素要配置,这么一来,就需要元素自身设置一个样式属性来覆盖父元素设置的全局样式。
1、align-self:元素自定义在单元格中的垂直对齐方式
假设第一个元素在容器内要垂直向下对齐,那么css可以这么配置:
.item1{
align-self: end;
}
如渲染图所示,第一个元素的垂直方式已经脱离了全局设定,变为向下对齐了。
2、justify-self:元素自定义在单元格内的水平对齐方式
这里同样对第一个元素设置,假设将它水平位置设置为左对齐,可以这么写:
.item1{
align-self: end;
justify-self: start;
}
如渲染图所示,第一个元素已经左对齐了
七、设置行与列在容器中的水平与垂直对齐方式
要对列或行的对齐方式进行配置的时候,那么在容器宽度或者高度上必须要空间剩余,否则谁知道各列或各行时怎样水平对齐或垂直对齐的呢?
换一个角度思考,能体现行或列对齐的场景时,容器在行或列上必须有空隙,如果有空隙,那么在对容器进行划分行或列时,就不包括使用了弹性单位 fr 或 auto,因为有了这些单位,容器就不存在剩余空间。
为了展示对各行和各列的对齐效果,新添加了三个元素,共九个子元素。网格修改为3x3:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,100px);
grid-template-rows: repeat(3,90px);
}
[class^=item]{
box-sizing: border-box;
background-color: blueviolet;
display: flex;
align-items: center;
justify-content: center;
border-width: 1px ;
border-style: solid;
border-color: aquamarine;
color: white;
}
</style>
</head>
<body>
<div id="con">
<div class="item1">item1</div>
<div class="item2">item2</div>
<div class="item3">item3</div>
<div class="item4">item4</div>
<div class="item5">item5</div>
<div class="item6">item6</div>
<div class="item7">item7</div>
<div class="item8">item8</div>
<div class="item9">item9</div>
</div>
</body>
</html>
1、align-content:设置各行垂直对齐方式
align-content表示对各行在垂直方向上的对齐方式。那么,要设置各行再垂直对齐方式为上下两端对齐,可以这么设置:align-content:space-between
:
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,100px);
grid-template-rows: repeat(3,90px);
align-content: space-between;
}
渲染效果
渲染图中,被画上了斜杆的区域,都是在行垂直方向上的两端对齐后,剩下的高度,将被平均分散于各行之间的间隙,剩余高度被平均分散于行间隙之后,看起来就是各行之间的间隙相等。
2、justify-content:设置各列水平对齐方式
justify-content用于设置各列在水平方向上的对齐方式。例如,我要各列在水平方向上右对齐,可以这写:justify-content:end
:
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: repeat(3,100px);
grid-template-rows: repeat(3,90px);
align-content: space-between;
justify-content: end;
}
3、place-content:align-contentu与justify-content的复合属性
place-content是align-content与justify-content的综合属性,其值有两个,由空格分开。空格前面的(第一个值),表示各行在垂直方向上的对齐方式,空格后面的值(第二个值),表示各列在水平方向上的对齐方式。
例如下来css配置方式就于上图的渲染结果一致:
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: repeat(4,3rem);
/* align-content: space-between;
justify-content: end; */
place-content: space-between end;
}
八*、容器区域命名
之所以将这种划分表格的方式,放到最后介绍,是因为这种划分表格的方式,在分隔线划分容器网格体系之外的,它是完全不一样的区域划分方式,且个人认为不太容易解释,放到最后,也是因读者而异吧,也许会有读者会认为这种划分方式更容易理解呢?
由于这种划分单元格的特殊性,现贴出如下基础代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
#con{
border: 2px solid blue;
margin:100px auto 0px;
width: 500px;
height: 400px;
display: grid;
}
[class^=item]{
box-sizing: border-box;
background-color: blueviolet;
display: flex;
align-items: center;
justify-content: center;
border-width: 1px ;
border-style: solid;
border-color: aquamarine;
color: white;
}
</style>
</head>
<body>
<div id="con">
<div class="item1">item1</div>
<div class="item2">item2</div>
<div class="item3">item3</div>
<div class="item4">item4</div>
<div class="item5">item5</div>
<div class="item6">item6</div>
</div>
</body>
</html>
基础代码渲染图
1、grid-template-areas:区域命名
这个属性的值是由一对双引号引起来的值表示一行属性,引号中使用空格分开的名称,每一个名称都代表一个单元格。这种划分区域的方式没有使用grid-template-columns与grid-template-rows灵活,适用于布局相对固定的页面。
同时每一对引号中,由空格分开的值数量都相同,因为每一对双引号都表示一行,不可能一行有3个单元格,而另一行却有2个单元格吧?如果真是这样,就没法划分网格了。
例如,我要划分3x3规格的网格。可以这么写:
#con {
border: 2px solid blue;
margin: 100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-areas: 'a b c'
'd e f'
'g h i';
place-items: top center;
}
渲染图如下:
以上结果中,item1所在的单元格名称为a
,item2所在单元格名称为b
,item3所在单元格名称为c
,item4所在单元格名称为d
,item5所在单元格名称为e
。解析图如下:单元格中对应的字母,就是当前单元格的名称。
如果要一个单元格只是占位,但是不想给他取任何名字,就把相应单元格的位置设置成一个小数点.
,如下:
#con {
border: 2px solid blue;
margin: 100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-areas: 'a b .'
'd e f'
'g h i';
place-items: top center;
}
解析图:
如上图所示,c区域已经没有了
2、grid-area:给元素指定区域名
这个属性是用于属性上的,不是用于容器上的,该属性通过grid-template-areas结合起来,可以实现排序单元格合并功能,它俩的组合可以说非常智能,以至于我现在还无法从原理上解释这种布局模式。这个是css3的强大之处吧,意识到自己实在学识不足,不足以解释这个方式。
给元素指定使用哪个区域后,元素的位置就会到指定的区域中去。例如,我要item1的元素到h
区域,对item1的配置可以这样:
.item1{
grid-area: h;
}
渲染图如下:
例如我要e和h统一合并为h
区域,那么可以这么设置:
#con {
border: 2px solid blue;
margin: 100px auto 0px;
width: 500px;
height: 400px;
display: grid;
grid-template-areas: 'a b .'
'd h f'
'g h i';
/* 注意这里我将第二排的e区域改为了h区域 */
place-items: top center;
}
[class^=item] {
box-sizing: border-box;
background-color: bisque;
text-align: center;
}
.item1{
grid-area: h;
background-color: teal;
/* 给h区域加上背景颜色 */
}
渲染图如下:
代码解释
:因为e和h区域统一为h区域以后,又因为item1使用的h区域,所以,我提前将h区域设置了不一样的颜色。这样item1元素就合并了两个单元格。
这个元素最大好处就是不用写使用分割线的方式合并区域了,同时具备了使用分隔线不具备的排序功能,这点是非常好的,同时它具有的智能程度也更高。