叶文全
(闽北职业技术学院 信息与工程系,福建 南平 353000)
随着网站从简单文档演变成复杂的交互式应用程序,并需要支持在多种不同尺寸的设备上运行,网页布局的需求复杂度也越来越高.传统的布局解决方案基于盒状模型,依赖float、position、display属性实现[1],难以解决特殊的布局需求(如垂直居中),网页布局对HTML的依赖较大,结构和表现的分离不够彻底.CSS弹性盒子布局(CSS Flexible Box Layout)的出现解决了很多布局问题,可以更加有效地对容器中的子元素进行排列、对齐和分配空白空间,弹性盒子布局适用于一维布局,非常适合组织应用组件和小型布局[2],但并不能很好地解决二维布局的复杂需求.为了解决复杂的二维布局需求,W3C推出了CSS网格布局(CSS Grid Layout)模块,该模块定义了一个二维网格布局系统,可以将网格容器的子节点指定到任意预定义布局网格的单元格中,这些布局网格可以是灵活的也可以是固定的[3],真正地实现了结构和表现的分离.
CSS网格布局由父元素和子元素两个核心构成.父元素称之为网格容器(Grid Container),网格容器通过指定行和列的数量,使其成为二维的网格容器.网格容器的直接子元素称之为网格项(Grid Item),网格容器可以灵活指定网格项在网格容器中的区域与相关属性.
图1 网格术语示意图
除了网格容器与网格项,该模块还定义了网格线、网格轨道、网格单元格、网格区域,如图1所示.
网格术语描述如下[4]:
网格线:构成网格结构的分界线,包括行网格线和列网格线.
网格轨道:两条相邻网格线之间的空间.
网格单元格:两条相邻的行和两条相邻的列网格线之间的空间.
网格区域:两条行和两条列网格线包围的总空间.
网格属性用于控制网格容器和网格项,包括网格容器属性和网格项属性.网格容器属性主要包括如下:
display:将元素定义为网格容器,属性值包括gird、inline-grid、subgrid.
grid-template-columns:指定网格列数及宽度,每个值代表一列及列宽,多列使用空格隔开,列宽支持具体值、百分比、等分值.
grid-template-rows:指定网格行数及高度,每个值代表一行及行高,多行使用空格隔开,行高使用百分比或等分值时,需要指定网格容器高度,否则指定无效.
grid-template-areas:用来指定网格模板,结合网格项的grid-area一起使用.
grid-template:用于定义grid-template-columns、grid-template-rows、grid-template-areas的缩写.
grid-column-gap/grid-row-gap:指定列/行网格线的大小.
grid-gap:用于定义grid-column-gap、grid-row-gap的缩写.
justify-items/align-items:指定网格项水平/垂直对齐方式.
justify-content/align-content:指定所有网格相对网格容器的水平/垂直对齐方式.
grid-auto-columns/grid-auto-rows:指定隐式网格的列宽/行高.超出定义的网格范围时,隐式网格被创建.
grid-auto-flow:指定自动布局顺序,对未明确放置的网格项进行放置.
grid:用于定义grid-template-rows、grid-template-columns、grid-template-areas、grid-auto-rows、grid-auto-columns和grid-auto-flow的缩写,同时,还重置grid-gap的初始值.
网格项属性主要包括如下:
grid-column-start/grid-column-end/grid-row-start/grid-row-end:通过网格线来指定网格项的位置,grid-column-start、grid-row-start是网格项的起始网格线,grid-column-end、grid-row-end是网格项的结束网格线.
grid-column/grid-row:分别为grid-column-start、grid-column-end和grid-row-start、grid-row-end的缩写.
grid-area:指定网格项名称或为grid-column-start/grid-column-end/grid-row-start/grid-row-end的缩写.当指定网格项名称时,可以被网格容器属性grid-template-areas引用.
justify-self/align-self:指定网格项水平/垂直对齐方式,适用于具体网格项的对齐设置,优先级高于网格容器属性justify-items、align-items.
在CSS网格布局中,为网格项分配网格区域提供基于网格线指定和使用grid-template-areas、grid-area结合基于网格模板指定的两种方式,下面结合实例进行研究.
创建一个网格容器,HTML代码如下:
创建一个3行3列的网格,自动放置网格项,CSS代码及布局效果如图2所示.
图2 自动放置网格项
为了说明CSS网格布局的强大二维布局能力及结构与表现分离的特性,对图3中的两种布局效果进行实现.
图3 需要实现的两种布局效果
1)使用基于网格线的方式实现图3左侧的布局效果,需要新增CSS代码:
.item1 {
grid-area:1/1/2/4;/*直接指定起止的行、列网格线,放置网格项*/
}
2)使用基于网格线的方式实现图3右侧的布局效果,需要新增CSS代码:
.item1 {grid-area:1/1/2/4;}
.item2 {grid-area:3/1/4/3;}
3)使用基于网格模板的方式实现图3左侧的布局效果,需要新增CSS代码:
.item1 {
grid-area:one;/*指定网格项名称,供网格模板引用*/
}
.wrapper {
grid-template-areas:
"one one one"
"…"
"…"
}
4)使用基于网格模板的方式实现图3右侧的布局效果,需要新增CSS代码:
.item1 {grid-area:one;}
.item2 {grid-area:two;}
.wrapper { grid-template-areas:
"one one one"
"…"
"two two."
}
与基于网格线的方式相比,基于网格模板的方式更加直观,可读性更强.以上对布局效果的实现,都是基于相同的HTML代码,不同效果的实现只通过改变CSS进行控制,同时,还突破了HTML元素先后顺序的限制.证明了CSS网格布局的强大二维布局能力及结构与表现分离的特性.
伴随着移动端的兴起,响应式布局越来越普及.在CSS网格布局模块中,引入了等分单位、repeat()函数、minmax()函数和auto-fit(自适应),为实现响应式布局提供了更强大的支持.
等分单位由CSS网格布局模块全新引入,其单位为fr,可以将网格容器划分成多个等分空间,等分空间会根据网格容器的大小自动调整尺寸,从而实现基本的响应式.如果需要根据网格容器的宽度自动调整列的数量,则需要使用auto-fit进行实现.
auto-fit可以根据网格容器的宽度及列宽来自动调整网格容器列的数量,从而实现更强大的自适应.同时,结合minmax()函数控制列宽的区间,不局限于具体的列宽,得到更好的响应式效果.
下面通过一个实例验证auto-fit在实现响应式上的表现,HTML代码同1.3节,CSS代码如下:
.wrapper {
display:grid; grid-gap:5px;
/* auto-fit自适应列数量,minmax指定列宽最小100px,最大1等分 */
grid-template-columns:repeat(auto-fit,minmax(100px,1fr));
grid-template-rows:repeat(3,100px);/* 3行,行高100px */
}
.wrapper > div {
background:#333;color:#fff;text-align:center;
font-size:36px;line-height:100px;
}
图4 auto-fit实现响应式
其响应式效果如图4所示.
auto-fit实现的响应式适合应用在列宽相同的场景,不规则的响应式应用场景还需要使用媒体查询结合强大的网格项放置进行实现.
媒体查询允许内容的呈现针对一个特定范围的输出设备而定制,而不必改变内容本身[5].通过使用媒体查询结合CSS网格布局,能够有效地降低响应式布局难度,提高易用性.
下面通过一个实例验证媒体查询结合CSS网格布局在实现响应式上的表现,HTML代码同1.3节,CSS核心代码及响应式呈现效果如图5、图6所示.
图5 超过1 024像素时的布局效果
图6 最大宽度1 024像素时的布局效果
通过对图5、图6中的CSS代码及布局效果进行分析,修改网格容器中的网格单元格及网格模板,便可轻松实现响应式布局.
截至目前,根据Can I Use官网提供的数据[6],主要浏览器对CSS网格布局的支持见表1、表2.
表1 桌面端浏览器及支持版本
表2 移动端浏览器及支持版本
多数主流浏览器都提供了对CSS网格布局的支持.同时,2018年2月6日,W3C工作组发布了CSS Grid Layout Module Level 2规范[7].CSS网格布局模块越来越成熟,在实际项目中广泛使用只是时间问题.
CSS网格布局中,网格容器所定义的网格单元格是看不见的,因此,需要有专门的网格检查器对布局进行调试.Firefox浏览器结合了网格布局工具,并统一实现为一个独立的布局面板,其中包括选定的HTML元素的盒模型及相关CSS属性,可以帮助开发者对网格布局进行调试.
在Firefox浏览器中对网格布局进行调试非常简单,只需要按F12进入查看器,选择查看器下的布局,就可以针对所需要的网格布局进行调试,如图7所示.
图7 Firefox网格布局调试
CSS网格布局是专门为了解决网页布局问题而创建的CSS模块,通过对其使用方法及布局能力的研究,验证了CSS网格布局具备强大的二维布局能力,真正地实现了结构与表现的分离.在响应式的实现上,提供了自适应支持,结合媒体查询可以轻松实现复杂的响应式布局.与CSS弹性盒子布局一起使用,综合二维布局与一维布局的优势,得出新一代的网页布局解决方案,并在不久的将来得到广泛应用.