CSS Grid
撰写时间:2023-05-29
修订时间:2025-12-10
CSS Grid是极富创造性的一种页面布局编排机制,是CSS不断进化过程中的集大成者。它丢弃了HTML中table标签的呆板机制,却紧密地结合CSS各种最新技术,从CSS的角度,重新实现了table的功能,并有过之而无不及。
CSS Grid的内容较多,学习起来有一定的难度,本教程通过丰富的实例,并借助于本站自行开发的强大的LiveEditor的实时运行功能,清晰地演示了CSS Grid的各项关键技术,能较为有力地帮助我们系统学习与掌握CSS Grid技术。
本教程覆盖了CSS Grid 1.0版本的内容。
本教程使用下面的CSS通用设置:
这样可更清楚地看到CSS Grid的效果。
如果需要在某个LiveEditor中改变这些默认值,则根据CSS的规则,可在LiveEditor的CSS
标签页中添加诸如下面的代码:
因为使用了更长、更具体的选择器,因此上面的CSS设置将比通用设置有更高的优先权限。
Grid父容器的设置
观察HTML
标签页中的内容,父容器共有5个一级子元素。由于这些子元素是块级元素,默认情况下,它们将各占一行,依序从上到下排列。
现在,将CSS
标签页中的内容全部删除,点击Run
按钮,可看到这种默认的排版情况。之后,重新刷新页面,恢复CSS
标签页中的初始设置内容。
应用CSS Grid的第一步,是将父容器div的display属性设置为grid,这样,该div将成为Grid容器(上面以橙色边框标示)。Grid容器下面的所有第一级子元素将由CSS Grid统一进行管理。CSS Grid的本质在于智能地、灵活地指定Grid容器下各个一级子元素的行、列位置。
第二步,设置grid-template-columns属性值。取名为template-columns
的含义为,在决定每一行中各个子元素应位于第几列时,均按此模板来设置。上面,该属性值被设定为100px 1fr,意为每行只排2个子元素,第1个子元素的宽度为固定的100px,第2个子元素的宽度属性值为1fr,则会占据该行中所有未使用的空间(这种空间,我们可称之为可用的弹性空间)。
排完第一行的元素后,还剩3个子元素。因为第一行已经没有空间,因此这3个子元素继续依照grid-template-columns: 100px 1fr的设置,依序在第2行、第3行中编排。第3行因为只有1个固定宽度的元素,因此右边还剩余许多弹性空间,其背景是斜纹灰底。
从左到右,依照模板格式编排子元素的各列,这是CSS Grid的最原始的设计理念。
练习:在LiveEditor中将grid-template-columns属性值设为50px 1fr 100px 25px,然后运行代码。查看结果,体会各种属性值的作用。
gap
可使用gap来设置Grid容器下的各个一级子元素相互之间的边距。
乍看之下,其效果好像是为Grid容器下的各个一级子元素设置了margin值,实际上并不是。下面是设置margin值的效果。
对比之下可以看出,gap只设置子元素之间的边距,但不设置子元素与父容器之间的边距。
grid-template-columns
正如上面所见,CSS Grid在Grid容器内按行、列的形式来定位各个子元素。
先按行、再按列来定位,还是先按列、再按行来定位,将产生不同的效果。grid-auto-flow属性决定使用哪种定位机制,当其值为row时,将先按行、再按列定位;当其值为column时,将先按列、再按行定位。默认值为row,因此,默认情况下先按行、再按列定位。
grid-auto-flow下面再详谈。现在我们先关注于在先按行、再按列定位的默认情况下,如何排列各列。
先按行、再按列来定位的具体细节是,将Grid容器下的各个一级子元素依序先排满第1行,当第1行排满后,将剩余的子元素依序排在第2行,依此类推。
显然,我们需要告诉CSS Grid,每行应排多少列的子元素。grid-template-columns目的正在于此,它显式地指定了各列的宽度。
显式与隐式的区别
声明了2个模板列,因而依此模板列的默认情况下,各个子元素将按每行2列的模板依序定位,直至结束。
但上面,我们还特意将B元素额外定位于第1行的第3列,由于它不在模板列范围内,CSS Grid将隐式地为其创建第3列。
排版顺序是,先定位用户自行指定位置的B元素,其余子元素则按模板列格式来定位。
能生成显式轨道 (explicit grid,这里中文使用显式轨道以指代) 并提供具体规范条件的属性有:grid-template-rows, grid-template-columns及grid-template-areas。
对于CSS Grid所自动创建的隐式轨道 (implicit grid), 可通过grid-auto-rows及grid-auto-columns来规范。
轨道列表
grid-template-columns的值可为一系列的轨道列表 (track-list),轨道之间以空格符隔开。
在轨道列表的值中,可指定一系列的轨道尺寸 (track-size),或使用reapeat函数来指定需重复的轨道 (track-repeat)。
下面以轨道尺寸的方式来指定轨道列表值。
轨道尺寸的语法为:
下面各节先依序考查轨道尺寸的各种值,再考查如何以轨道重复的方式来指定值。
fr的作用
fr有两种格式:一是诸如3fr(前面的数值大于等于1)的格式;二是诸如0.3fr(前面的数值小于1的格式)。下面分别考察。
数值大于等于1的fr
fr是可自动变长的数值。上面代码,grid-template-columns属性值为1fr 2fr 30px 3fr,则CSS Grid先在该行中优先确定C元素的宽度,然后,将该行所剩的空间在其他几个具有fr属性值的子元素之间再进行分配。
fr意为部分
,数值为百分比的形式,我们也可以理解为单位
。上面的例子中,第1个子元素占1个单位的宽度,第2个子元素占2个单位的宽度,第4个子元素占3个单位的宽度。因此,若说A的宽度是1个单位,则B的宽度是A的2倍即2个单位,D是A的3倍,即3个单位。
1fr确定了分子为1
,分母呢?分母为该行中所有具有fr属性值的子元素的数值总和。因此,上面分母为1 + 2 + 3 = 6,则A元素宽度为总宽度除去C元素宽度之外的1/6,B元素宽度为2/6,D元素宽度为3/6。如果一行只有一个具有fr属性值的子元素,则不管其数值是多少,都会占去所有的弹性空间。因此,它与n%的算法不一样。
我们可以这样思考。先确定一个1fr的元素,然后在剩下的空间中,按照其他元素是该元素的几倍来确定。如A元素的宽度为1fr,如果B元素应是A元素的2倍,则取2fr
。余此类推。
数值小于1的fr
grid-template-columns的值中可以使用0.1fr的形式,即fr的前面是小于1的小数。这种方式类似于n%的效果。下面看各个小数之和的情况。
和等于1
在理想的情况下,一行中各个元素小数点之和应等于1。
此时,各元素能自动铺满所在行的可用弹性空间。
和小于1
此时,各元素按指定的比例占用所在行的可用弹性空间,但留下了0.2的可用弹性空间未使用。
既然仍有可用弹性空间,如果再加上一个固定宽度的元素呢?
其结果是,先保证固定宽度的C元素的宽度,然后再将剩余的可用弹性空间按0.2、0.6、0.2的比例依序分配给A元素及B元素,由于各元素小数点之和未达到1,因此仍留下0.2的可用弹性空间。
和大于1
由于总和超过1,此时,两个元素将占满所在行的可用弹性空间,且保持之间的比例0.9:0.3。
这个效果,与grid-template-columns: 9fr 3fr;的效果完全一致。
因此,当出现两个超大的小数点,且这两个小数点的值又一样时,如:grid-template-columns: 0.9fr 0.9fr;,当您看到它们两个在如下所示的渲染时表现为平分可用弹性空间,就不会感到奇怪了。
auto
auto也是一个会自动变长的属性值。但,与fr不同的是,auto有较多的细节需要注意。
单独使用auto
当每一行只有一列,且其值为auto时,该列会自动铺满可用弹性空间。
当一行有多个其值均为auto的列时,以每列宽度都相等的方式自动铺满可用弹性空间。
auto与固定宽度值共用
当auto与固定宽度值共用时,所有auto列会自动按比例铺满剩余的可用弹性空间。此时auto相当于1fr的效果。
auto与fr共用
当auto与fr共用时,auto降格了,不再有弹性拉伸的作用,仅保留最小宽度,将其拉伸的优先权让位于fr,由fr来铺满剩余的可用弹性空间。
minmax
minmax函数允许特定列在值域内取值。第1列的宽度最小值为400px,最大值为450px,第2列是固定的50px。
如果您是在桌面电脑上访问此页面,则由于浏览器客户端有许多空间,而A元素最大值只有450px,因此每行会留出许多空白,透出我们特意设定的斜纹灰底(该部分为CSS Grid所管理的空间)。如果拉动浏览器边框以改变其宽度,当宽度越来小时,CSS Grid会优先使用多出的斜纹灰底空间,这样斜纹灰底空间会越来越小,从而确保尽可能使A元素获得最大值。而一旦多余空间耗尽,则开始减少A元素的宽度,但确保其宽度至少为400px。当继续减少浏览器的宽度,已经不能满足A元素与B都同时出现在可视区域内时,如果父容器允许,则出现水平滚动条,从而创建出更多的空间。
一句话,如果空间足够,则优先保障该元素的最大值;如果没有空间,至少保障该元素的最小值。
举个例子,我们对某人说,如果空间充裕,你也不要占得太多,得留出一些空间给别人;但如果空间太小,我可以保证你至少获得100平米的空间。
理解并掌握这个属性值,在分别为桌面及移动客户端布局时非常有用。我们可以为某个核心元素先设定一个必需的最小值,然后再设定一个合理的最大值。这样就不会因为空间大幅改变后而导致冒然地失去应用功能。
练习:在LiveEditor中将grid-template-columns属性值设为minmax(100px, 1fr) 50px;。这种布局,可让A列吃掉所有多余的空间,但又确保最小值。
还有专门的min函数及max函数,语义上更容易理解了。
min-content, max-content, fit-content
这3个属性值涉及到父容器如何包裹子元素的问题。
八卦中以五行生克来定吉凶。五行生克可以很简单,但蕴涵了许多朴素而深奥的哲学原理。
外层div包裹了两个子元素,一个是img,另一个是p,它们都是块级元素。由于外层div同时也是块级元素,因此它独立占了一整行,从而导致图像及段落的右边都留下了不好看的空间。现在,我们的目标是,如何让外层容器自动紧密地包裹这些内部子元素?
设置外层容器的width属性值为max-content:
八卦中以五行生克来定吉凶。五行生克可以很简单,但蕴涵了许多朴素而深奥的哲学原理。
外层容器的宽度值取自于两个子元素中最大的宽度值,即段落的宽度值。与上面的结果相比较,段落右边是没有空间了,但图像右边还有,照样不好看。
设置外层容器的width属性值为min-content:
八卦中以五行生克来定吉凶。五行生克可以很简单,但蕴涵了许多朴素而深奥的哲学原理。
这时,外层容器的宽度值取自于两个子元素中最小的宽度值。两个子元素虽为块级元素,但它们还是存在区别的:图像的宽度不能自动改变,而段落的宽度则可以通过断行而自动改变。因此,此时则取图像的宽度作为外层容器的宽度值即可。
fit-content也是一个CSS属性名。它的意义在于,外层容器所使用的空间,不会大于max-content。因此,它的效果与max-content一样。
需注意的是,同时存在fit-content()的CSS函数。
repeat函数
当多列的数值出现多次重复时,可使用repeat函数。
repeat(n, unit)
意为,重复3次80px的宽度,重复次数放在前面,单位放在后面。因此,它与下面的代码是等效的:
repeat(n, unit unit)
上面,需重复2次,且每次需要重复的宽度值为:80px 50px,则可使用repeat(2, 80px 50px)的形式。
repeat auto-fill
repeat(auto-fill, unit)
上面的repeat(n, unit...)先确定每一列的具体宽度,再指定了每一行应有多少个这种宽度的列。因此,不管父容器的宽度是多少,每一行的列数是固定的。当该行没有空间而排不下这些元素时,则通过在父容器显示水平滚动条的方式来添加空间。
但我们往往还有另外一种需求,即,如果水平空间够宽敞,但希望排3个子元素,如果水平空间不够,则只需排2个子元素就行了。显然,这里子元素的个数是不确定的,因此不能使用上面的格式。repeat(auto-fill, unit)可用以解决这种特定的需求。
repeat(auto-fill, unit)含义是,一次排一个宽度为unit
的元素,再看剩下的空间能否排得下第二个这种宽度的元素。如果剩下的空间排得下第二个,则将第二个元素排在第一个元素的右边。然后再看第三个、第四个, ...,依此类推。若遇到剩下的空间不足以排得下新的元素,则将新的元素排在第二行。在新行中,再重复上面的算法。
这样,只要我们指定的列宽,CSS Grid就会根据可用空间来自动安排在每行上的元素个数,从而既保证了列宽,又能在有限的空间内尽可能多地排上各个元素。
repeat(auto-fill, minmax)
上面我们指定每个元素为固定的150px的宽度,因此会造成每行右边会有留白。如果希望各元素还能自动铺满一行,则可以将每列的宽度指定minmax(150px, 1fr):
这样,每列宽度不会少于150px,并且当每行右边的留白又不足以排下一个新元素时,则会平等的拉伸每个现有元素的宽度,以自动铺满整行的空间。
它的效果为:
- 每一列的宽度值最小为150px。
- 至于每行能排多少列,由CSS Grid帮我们自动计算。
- 当每行上剩有多余的弹性空间时,将同时等量地拉伸各列以铺满该行。
这样,在保证每列最小宽度值的同时,由CSS Grid自动帮我们计算列数,又能让每行不留空白。在许多场合下,我们确实需要此功能。
然而,这里有一个小问题:如果每列的宽度太小,即使都排完了所有元素,auto-fill也不会自动铺满整行。如下所示:
repeat auto-fit
auto-fit可以解决上一节中的问题,即使每列的宽度太小而有留白,这些留白的宽度将变为0px
,也即产生了塌陷(collapse),从而导致auto-fit可以自动拉伸每个元素的宽度以铺满整行。
综上,如果需要拉伸效果,而又无需考虑元素的最小宽度值是否过小,则应使用repeat(auto-fit, minmax())的代码。
grid-template-rows
grid-template-rows设定各行高度的模板。
未指定grid-template-columns及grid-template-rows
当既未指定grid-template-columns,也未指定grid-template-rows时,排版效果是每行一个铺满整行的元素。
注意,尽管上面每个子元素都是行内元素span,因由CSS Grid管理而具有块级元素的特征。
指定行数正好等于子元素数量
指定模板行的数量少于总行数量的情况
上面子元素共有5行,而我们仅指定了3行,则第4行、第5行的高度取相应子元素的初始值。
我们使用grid-template-columns指定模板列时,如果模板列数少于所有子元素的数量,则会自动产生断行,新行中的子元素继续依照模板列的格式来编排。而grid-template-rows不会重复使用模板行的设置。如果我们指定的模板行不包含特定行,则特定行取默认高度值。
在许多情况下,总行的数量并非总是可以确定下来。那么如何自动涵盖所有的行?
使用grid-auto-rows为非模板行设置高度
grid-template-columns应对模板行,对于非模板行,可以使用grid-auto-rows来应对。
上面模板行只指定了3行,则最后2行为非模板行,通过设定grid-auto-rows: 80px,我们将所有这些行的高度统一设置为80px。
使用repeat来遍历所有的行
grid-template-rows可以使用repeat函数来遍历所有的行。
但这种方式,与不设置grid-template-rows一样。如果我们改为grid-template-rows: repeat(10, 50px);,则会看到,比总行数量多出的设置,会导致在下面产生了不必要的空间。这种方式不可取。
因此,还是像上节一样,使用grid-auto-rows: 80px;的方式更为稳妥。
CSS Grid布局术语详解
CSS Grid有多种精准定准子元素的方法,我们需要先了解CSS Grid相关术语,才能做到深刻理解随心所欲地予以编排。CSS Grid的结构示意图如下。

根据上面所学的知识,我们可以精准地用代码复现此示意图,并在相应的位置放置子元素。
共有A, B, C, D, E, F等6个子元素,每列排2个元素,故共有3行。
最外面的4条虚线所围成的区域称为grid,它用以整齐地排列各个子元素。图中的grid共有3行2列。
先看示意图中列的情况。用3条垂直竖线将每行分割为2列。示意图中,第1条垂直竖线用line 1
表示,第2条垂直竖线用line 2
表示,第3条垂直竖线用line 3
表示。
同理,示意图使用4条水平横线将整个grid分割为3行。从上到下,其名称分别为line 1
, line 2
, line 3
, line 4
。
对于这些分割行或列的虚线,我们统称为grid line。两条相邻的同向的grid line之间区域称为grid track。因此,它是一行或一列的统称。例如,在水平方向上,A与B在同一grid track上,而在垂直方向上,A, C, E在同一grid track上。
这些grid lines将整个grid划分为6个区域,用于分别放置A, B, C, D, E, F等6个子元素。我们将这些可以放置子元素的最小区域称为grid cell。在上面的例子中,A, B, C, D, E, F均独立占具一个grid cell。
若干个相邻的grid cell可以组成一个更大空间的grid area。搬用电子表格中的用语,grid area就是指若干个相邻的grid cell合并后的合并单元格。
Grid line的定义与引用
grid-row-start, grid-row-end, grid-column-start, 以及grid-column-end这4个属性需要引用具体的grid-line。
使用Grid line的序号
每条Grid line都有自己的序号。从左到右及从上到下,序号从1开始,逐渐增大。也可以使用负数来表示倒数的序号,-1
表示倒数第1行或倒数第1列,-2
表示倒数第2行或倒数第2列,依此类推。Chrome, Safari, Firefox等浏览器的开发者工具可以查看CSS Grid的Grid line的序号。Chrome的效果如下图所示:

现在,我们准备将B排在1行1列,F排在2行2行。
第1行第1列这个grid cell所在的行由序号为1
和2
的两条grid line分割。因此,我们用grid-row-start: 1;来指定所在行从1
这条grid line开始,用grid-row-end: 2;表示至2
这条grid line结束。
同理,用grid-column-start: 1;来指定所在列从1
这条grid line开始,用grid-column-end: 2;表示至2
这条grid line结束。这样便达到精准定位的目标。
对于F元素而言,它的行始于第2条grid line,终于第3条grid line;它的列始于第2条grid line,终于第3条grid line。
我们也可以使用负数的序号为子元素定位。例如,F元素也可这样指定:
上面,我们显式地指定了B与F元素的位置,CSS Grid将优先保证它们两个的位置,然后再将其他元素依照声明的次序,逐个排进模板列及模板行中。
为Grid line命名
除了直接引用grid line序号之外,我们还可以为grid line取名,在CSS Grid中称为custom ident,即custom identifier
(自定义标识符
)。
一般命名方法
首先,在设置grid-template-columns或grid-template-rows时,在相应的单元格左右或上下的grid line出现的地方,加入相应的名称,名称用[ ]
包围起来:
其次,子元素引用这些grid line的名称,但去掉定义名称时所加上的[ ]
:
一般情况下,我们需要引用哪些grid line时,才需要为它们命名。不需要引用的,就没必要浪费时间给它们命名了。
grid-template-columns与grid-template-rows的grid line的名称可以重合,不用担心命名会起冲突,因此它们应用的语义环境不一样。
上面,我们直接从具体grid line的角度,将它们取名为第几条线
,这当然比不上直接引用序号便捷,目的仅在于演示而已。当然,您可以根据自己的语义环境,为它们取更有意义的名称。
遵循约定的命名方法
现在,我们从子元素的角度,为围绕其的grid line命名。
我们将排在B元素左右两边的两条grid line分别取名为item-b-start
及item-b-end
,表示这两条grid line分别是B元素的起止之线。这是以元素为核心的命名方法。
上面的命名方式以分别以-start
及-end
作为后缀命名。CSS Grid欢迎这种命名方式,并约定,若以这种方式命名,在引用该名称时,无需引用其后缀部分。
上面,我们将围绕B元素的两条垂直grid line分别命名为b-start
及b-end
,而在引用时,只需指定为b
即可。
在查找时,CSS Grid会自动根据其所在的属性名称,自动为它们加上相应的后缀。
在下面的为grid area命名一节中,我们将会看到,CSS Grid就是根据这个特性添加了隐式的名称。
多条Grid line可以共享同一名称
上面,在声明时,3条垂直的grid line均使用同一名称v-line
,且在引用时也均一样地引用了v-line
。CSS Grid会自动地从左到右地提取对应的grid line。
如果我们希望改变CSS Grid的这种默认行为,例如,我们希望B元素从第1条grid line开始,至第3条grid line结束,则可以通过在名称后面添加[space] index
的方式进行指定。index
的值也可为负数。
一条Grid line可以有多个名称
同一条grid line可以有多个名称,各个名称之间用空格隔开。引用时,可使用该线条的任一名称。
使用span来跨行或跨列
指定单数的起始行列,再指定复数的终止数量
为grid-column-start指定一个起始列,再通过span n为grid-column-end设定一个跨度数值。
上面初始指定的列数为2列,如果指定span n后超过了指定的列数,则会隐式地添加多余的列。例如:
C元素要求有3列的宽度,则模板列将变为3列。而之前的A, B元素先按默认的2列排列,在变为3列后,其所在行会有留白。
但如果C元素之前的A或B元素已经先排,则A或B元素所在行不会留白。
grid-column-start跨列
注意,不能在span
的前面再引用一行或一列,例如:grid-column-start: 1 span 2;。这是错误的。
grid-column-end跨列至指定的列名
注意,grid-column-start不支持这种设置值。
同名的跨域
跨至中间的名称:
跨至最后一个:
直接指定最后一列就行,不能使用span
。
小结
使用grid-row-start这些属性名的不便之处在于,在指定grid line时,我们需要脑补这些grid line的序号。此外,细节比较繁杂。
grid-row及grid-column
grid-row指定元素所在的行,grid-column指定元素所在的列。
grid-row是grid-row-start及grid-row-end的简写。grid-column是grid-column-start及grid-column-end的简写。
基本用法
上面,我们将A子元素排在第1行第2列,将B子元素排在第3行第1列。代码简洁明了,非常直观。
跨行或跨列
对于A元素,使用grid-row: 1 / span 2;来指定所在行从第1行开始,跨2行。对于B元素,使用grid-column: 1 / span 2;来指定所在列从第1列开始,跨2列。
指定起止行列
A元素,使用grid-column: 2 / 4;来指定其单元格从第2条grid-line开始,到第4条grid-line结束。由于模板列只有2列,故会自动添加第3列至模板列中。
注意比较:
grid-column: 1 / span 2: 从第1列开始,跨2列。引用的是grid-cell。
grid-column: 1 / 2: 从第1条grid-line开始,至第2条grid-line结束。引用的是grid-line。
使用grid-template-areas为空间命名
基本语法
Aritcle title
paragraph 1
parapgraph 2
第一步,先使用grid-template-areas将父容器划分为几大部分,并为它们相应命名。跨行或跨列的,重复上行或上列的名称即可。第二步,将各个子元素通过grid-area与所命名的区域对应起来。
区域名称并无太多限制,甚至可以使用单个英文字符。如果grid-area允许出现留白,则用单个或多个.
来代替。
练习:将grid-template-areas的最后一行属性值改为... footer ...
看看效果如何。
空间命名的便利之处
空间命名的一个便利之处是非常方便做整个版面的调整。
Aritcle title
paragraph 1
parapgraph 2
上面的代码,在桌面电脑上浏览时,效果与上节一致。而当客户端宽度小于等于400px
时,此为移动设备的宽度,则只显示主干区域,并将两个非主干区域隐藏起来。
grid-template属性名称
grid-template是grid-template-rows, grid-template-columns及grid-template-areas的简写。
基本用法
以行 / 列
的格式来定义。
定义了3行及2列。其效果等同于:
融入grid-template-areas
再进一步,将上面的行的定义改写为grid-template-areas的形式:
等同于:
相比之下,使用grid-template定义grid areas,然后将各行的高度分别列在各行名称的右边,反倒更为直观。
grid属性名称
grid是grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, 以及grid-auto-flow的简写。
grid-auto-flow属性
grid-auto-flow属性决定先排行还是先排列。
如果属性值是默认值row
,则先依据每行中所有列的数量,先排完一行的各列,再排另一行。
先排行。每行中有2列,则A, B子元素先排在第1行,然后另起一行,继续排完后面的子元素。
而如果属性值是column
,则先依据每列中各行的数量,先排完一列的各行,再排另一列。
先排列,每列有4行,故A, B, C, D先排在第1列,然后再另起一列。
grid-auto-flow的属性值还可以是row dense
或column dense
。用于决定在前面已经排过的位置中如果出现留白,是否可以由后面的元素排在留白的位置。看下面的例子。
优先按行到排列。我们指定A元素必须排在第3行,因此,B与C元素先排在第1行。接着到D元素。由于我们指定该元素必须在第2列,因此它排到了第2行的第2列,导致第2行的第1列留白。E, F元素则跟在A元素之后排列。
现在,将grid-auto-flow的属性值改为row dense
。
与上面不同的是,紧跟在A元素之后的E元素,看到D元素的前面有留白,就在该留白处予以排列。即,后面排列的元素自动填补前面的留白。
再看优先按列排列的情况。
A先排在第1列的第3行,导致该列前面2行留白。到C时,已另起1列至第2列,此时由于D被指定为必须排在第2列,其优先权高于C,因此,先排D再排C。E及F排在第2列的最后。
将grid-auto-flow的属性值改为column dense
。
B与C则迫不及待地跳上去填补留白了。
grid属性的用法
很多时候,名称越短,功能更丰富,使用更简单,但在CSS中却相反:CSS的属性名称越短,其越难理解与掌握。下面是grid-area简写金字塔:
| grid-area | |||
| grid-column | grid-row | ||
| grid-column-start | grid-column-end | grid-row-start | grid-row-end |
下面是grid简写金字塔:
| grid | ||||
| grid-template | grid-auto-columns | grid-auto-rows | grid-auto-flow | |
| grid-template-rows | grid-template-columns | |||
对齐
整个grid在grid container中的对齐
在grid container中使用justify-content使整个grid在grid container中水平对齐,在grid container中使用align-content使整个grid在grid container中垂直对齐。
上例中灰底部分为grid container所占用的空间,也即grid布局的空间。由于我们指定每行中的2列分别为150px
及100px
,因此不能占满整行,在水平方向上有留白。同样,每行的高度也均使用默认的固定值,3行总高度也不能占满整个grid container的高度上的空间,因此在垂直方向上也有留白。
当grid container有留白时,整个grid便可在其中上下左右移动。此时即可在grid container元素中使用justify-content及align-content来控制grid的偏移位置。
justify-content的值包括:normal, space-between, space-around, space-evenly, stretch, safe, unsafe, center, start, end, flex-start, flex-end, left, right.
align-content的值包括:normal, first, last, baseline, space-between, space-around, space-evenly, stretch, safe, unsafe, center, start, end, flex-start, flex-end.
将上面各个值分别代入justify-content及align-content,观察实际效果。
在父容器中统一设定子元素应否拉伸
默认情况下,grid container下所有子元素都会自动拉伸以填满grid布局空间。例如:
共有2列,第1列占用了150px
的grid布局空间,第2列占用该行中grid布局空间的剩余空间。并且,由于grid布局空间最小高度为150px
,在高度上的空间也很充裕,每个子元素的高度也被拉伸了。
但,查看每个子元素,其内容均只有一个字母,它们本身的内在尺寸(intrinsic size)实在无法铺满它们所实际占用的grid布局空间。
上面的代码只是确定了每个grid cell的大小。而在空间较大的grid cell内,如果再对子元素进行进一步的布局?
justify-items及align-items应运而生。它们均应用于grid container中,用以统一设置所有子元素的属性。前者用于水平方向,后者用于垂直方向。
与上一个例子相比较,各个子元素仍呆在对应的grid cell之内,但每个子元素的边框仅围住了它们的内在尺寸的空间,并且依据我们的代码,在水平方向上靠右对齐,在垂直方向上居中对齐。
justify-items的值包括:normal, stretch, first, last, baseline, safe, unsafe, center, start, end, self-start, self-end, flex-start, flex-end, left, right, center, legacy(默认值)。
align-items的值包括:normal(默认值), stretch, first, last, baseline, safe, unsafe, center, start, end, self-start, self-end, flex-start, flex-end.
将上面各个值分别代入justify-items及align-items,观察实际效果。
在子元素中单独设定该元素应否拉伸
上一节,我们在父容器中统一设定了各个子元素应否拉伸,相对应地,justify-self及align-self可应用在各个子元素上,以设定该子元素不同于父容器统一设定的情况。
在父容器中,我们通过justify-items及align-items统一设定了所有的子元素应水平靠右垂直居中对齐,而在A元素中,通过justify-self及align-self将该元素改为水平及垂直均拉伸。
结语
CSS Grid的编排策略非常灵活,能应对各种各样的需求。然而,健壮的功能往往意味着庞大的身躯,因此,它实际远比从表面看上去时要复杂得多(本文的文本内容加上源代码,超过了2100行,全文历时将近半个月才完成)。
本教程通过丰富的实例,涵盖了CSS Grid最常用的90%以上的内容,希望对掌握并熟练驾驭CSS Grid能起到较大的帮助作用。
