本文由大漠根据Constantin Kichinsky的《Introduction into CSS3 Grid Layout. Working with grids》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://www.splashnology.com/article/introduction-into-css3-grid-layout-working-with-grids/5762,以及作者相关信息
——作者:Constantin Kichinsky
——译者:大漠
前言
在我看来,CSS3模块家族中,CSS3网格布局模块是最有趣的一个。W3C官网自发布草案到今天不到一年时间。有一点必须注意,早在2007年 宣布的WD版本中,有些名称和语法有一些变化,但是他们具有相同的本质。今天模块正在前速向前,在IE10中已经初步实现,希望新的特性在将来能得到支持以及其他流行浏览器也将支持这个模块。
为什么我们需要网格布局?
CSS3网格布局模块的一个任务是帮助我们处理非常简单和清晰的任何web-imposer(不仅),很有可能是一个内容块在一个虚拟的网络位置。
与旧的表格方法相比,表格是基于一个使用的表,这里的具有清晰的文档语义和内容与结构的分离。在一个模板中使用不同的结构标签,使用多个浮动和手动计算实现一个布局是困难的,这里介绍的方法变得非常简单和清晰。与绝对定位相比,网格更具灵活性。与当今天流行的CSS/JS库相比,这些库使用网格都需要指定相应的类名(作为一个示例,比如bootstrap和yui css grids),而在网格布局模块中是不需要额外增添这些类名。
太爽了!现在就等浏览器广泛的支持了。然而,如果你想去做一个Win8那样Metro风格的应用,还在使用HTML/JS,更为关键的是,你可使用CSS3网格布局模块来制作布局,这样可以兼容移动端,使用简单,而且实用。
基本
首先让我们从示例中了解网格布局。想像一下,你需要制作一个经典的三列布局,这样的布局大约需要一个以下的标记:
<section> <header>Title</header> <nav>Menu</nav> <article>Content</article> <aside>Notes</aside> <footer>Footer</footer> </section>
我们需要一个如下图所示的三列布局:
这是一个经典的布局,因此我们将不太关注传统的方法实现这个多列布局采用的是什么标记。我们关注的是使用CSS3网格布局我们能做些什么?(在个实例中,我跳过了浏览器前缀,在实践中应该为例子添加IE的前缀“-ms-”)。
下面是这个例子中使用的CSS代码:
section { display: -ms-grid; grid-columns: 150px 1fr 200px; grid-rows: 50px 1fr 50px; } section header { grid-column: 2; grid-row: 1; } section nav { grid-column: 1; grid-row: 2; } section article { grid-column: 2; grid-row: 2; } section aside { grid-column: 3; grid-row: 2; } section footer { grid-column: 2; grid-row: 3; }
你要指定一个容器(section)为网格,里面的内容都位于网格上和使用grid-columns、grid-rows属性设置一个虚拟网格(下面会介绍这些属性的作用)。进一步我们应该为容器内的元素指定位置。
整个包括:
- 虚拟网格:容器中的grid-columns和grid-rows组成。
- 元素旋转:grid-column和grid-row
现在让我们来看看这些细节和更多的可能性。
虚拟网格
网格轨迹:行与列
为了能放置元素,需要创建一个虚拟网格。因此我们有必要的描述一下网格轨迹中的行和列:
#grid { display: grid; grid-columns: 150px 1fr; /* 两列 */ grid-rows: 50px 1fr 50px; /* 三行 */ }
网格线
网格轨道介于两网格线之间,围着他自身转,每个网格轨道在他自身的上面、下面、左面和右面都有一个网格线。
如何设置元素放置在网格哪个位置,需要明确指定从哪条水平线和垂直线开始。
#item { grid-column: 2; grid-row: 2; }
默认情况之下,元素占据的空间都是在指定的网格线之下。(这样看起来像是数单元格数一样,我们元素就类似放置在单元格中)。
扩展单元格
扩展元素占据几个网格单元格,我们一般都是使用grid-now-span和grid-column-span属性来实现:
#item { grid-column: 2; grid-column-span: 3; grid-row: 2; grid-row-span:2; }
默认情况,这两个属性的值都是“1”。可以根据需求在这上面进行扩展。
重复轨道
经常根据容器结构模板需要选择网格。
#grid { display: grid; grid-columns: 24px 120px 24px 120px 24px 120px 24px 120px 24px; grid-rows: 1fr 24px 1fr 24px 1fr 24px; }
它将更清楚的描述一个更清晰的网格,上面的例子我们可以用这样的方法来描述:
#grid { display: grid; grid-columns: 24px (120px 24px)[4]; grid-rows: (1fr 24px)[3]; }
模板本身的参数放在括号中,后面用方括号指定重复的次数。
现在,当我们知道网格线的基本描述,接下来我们再次回到网格的轨道和尝试理解一些具体的度量单位。
度量单位
正如你所注意到的,这里使用一个特殊的单位为指定一些列和行的大小——1fr。现在,我们将讨论这个和其他可能的值用来指定长度。
在描述列宽和行高,可以使用下面的单位和值:
- 线性尺寸:标准的单位,用来指定长度。CSS3值和单位模块中有详细的描述,如pt、px、em、vw等等。
- 百分比:通过一个网格容器尺寸的百分比来指定网格轨道。(如果网格的宽度和高度取决于内容大小,那么结果是无限的)
- 分数:是一非负数的数值,后面带有一个fr单位,每个分数值大小根据根据数值的比例来决定。(详细的见下面介绍)
- max-content:是一个关键词,根据网格轨道内元素最大长度来决定。
- min-content:是一个关键词,根据网格轨道内元素最小长度来决定。
- minmax(min,max):一个集值的范围。(工作原理可以描述为:minmax(p,q)=max(p,min(有效填充,q))——从一个最小值到一个最大值的可用空间范围)。
- auto:是一个关键词,等于minmax(min-content,max-content)。
分数值
让我们试着理解,分数值是如何工作的?一个网格占据了一定宽度和高度的空间。这可能取决于内容,严格上说是固定的或占据所外部容器所有可以访问的空间。进一步的说,你的网格轨道的列数和行数是可以明显设置的。如何设置他们的尺寸,对于其他的一些部分取决于内容的长度。
现在我们访问了一个网格容器,他的横向和纵向的宽度减去内容的宽度和高度。额外的空间按照数值的比例进行划分。
在上面的示例中,显示了三列按宽度的2:1:1和两行按高度的5:2划分列宽度和行高度。
示例
从规范草案中复制过来的一个示例,让我看到不同类型的关键词和值:
#grid { display: grid; grid-columns: 100px 1fr max-content minmax(min-content, 1fr) }
具体描述如下:
- 从第一条线开始。
- 距离第一条线的100像素处。
- 另一条线是其他空间的1/2处,从第二条开始。
- 从第三条线开始最大内容列处。
- 最后一条线距离第四条线,他等于元素最小宽度或额外空间的1/2之间。
这里有细微的差别,用户内部出现最大和小值,他们正在考虑一个分数值作为最大位置。分数标志着最低的位置被认为是等于0,详细的细节请参考规范。
下一步我们将试图找出元素代替它们位置之间的网格线(网格内的单元格)。
绑定元素
现在,把元素绑定到网格行中会出现一个问题:他们是如何放在网络线之间?
绑定元素在网格的边缘是依靠grid-column-align和grid-row-align属性来控制的。他们的属性值主要包括:
- start
- end
- center
- stretch
这些值从名称上就告诉我们他们的展示行为是什么。我只会注意到,在每个案例的问题是关于定位元素与其容器之间的距离。这两个属性的默认值是stretch,表示拉伸元素至容器一样大小。
元素绑定在列(水平方向)对应的是文本方向(例如一些阿拉伯语,是从右边开始到左边结束)。元素绑定在行(垂直方向)对应是块的方向(顺便说一句,这意味着一些东亚语言,行和列可以改变他们的位置)。
控制层
下一个重点来了,元素的位置在网格内如何布置。如果两个元素都绑定在同一行中,或者扩展排列到相同的单元格,那么会发生些什么?
最重要的需要理解一些细微的差别,元素放置在网格中不会直接影响彼此的位置。如果你将十个元素都绑定到网格的水平方向第二条网格线和垂直方向第三条网格线起始处。那么默认情况他们都将取代他们的位置,层叠放在一起。每个元素都绑定到网格相对应的角落。这些元素可以影响的只有网格轨道,如果他们被绑定,那么它将会影响内容的尺寸。
要控制这些层的显示顺序,当前规范版本使用的是z-index属性,允许管理网格内元素的层级。
备注:在基于ie10的前一个版本规范,使用一个grid-layer属性来指定网格内元素层级关系,而没有使用z-index。然而,进一步的讨论过程中,工作组决定重新考虑使用z-index这个属性。
看一个例子:
#grid { display: grid; grid-columns: (1fr)[3]; grid-rows: (1fr)[4]; } #A { grid-column:1; grid-row:3; grid-column-span:2; } #B { grid-column:1; grid-row:1; grid-row-span:2; /* grid-layer: 10; */ z-index:10; margin-top:10px; } #C { grid-column:1; grid-row:1; grid-column-span:2; margin-left:50px; } #D { grid-column:2; grid-row:3; grid-row-span:2; grid-column-span:2; margin:10px 0 0 10px; } #E { grid-column:2; grid-row:2; /* grid-layer: 5; */ z-index:5; margin: -20px; }
CSS3 网格库
到目前为止,仅在IE10+的浏览器可以支持网格布局模块,其他浏览器还不支持。但是它可以使用js库eCSStender和扩展的网格对齐,他们支持下面的属性:
- display:grid
- grid-columns和grid-rows
- grid-column和grid-row
- grid-column-span和grid-row-span
可以查看这个实例。
关于未来
最后,让我们稍微了解一下,CSS3网格布局模块在未来会有哪些的变化。
以下提到的可能性是在草稿规范中提到的,但现在还没有浏览器支持这些特性。将来能否支持取决于W3C组织。
明确指定元素结束位置的网格线
可以对元素占据的网格的开始网格线,还可以指定他们的结束网格线:
#item { grid-column: 2; grid-row: 2 4; }
和“span”机制不一样,他指定了一个元素在水平方向和垂直方向必须跨越多少单元格,可以明确的为元素指定从哪行开始到哪行结束。它也可以轻松的使用网格线名称。
网格线命名
为了方便行,可能会为其命名。它是通过在适当的位置插入字符串值,用来描述网格轨道。(如果实际需要,可以定义向个名称,比如说从语义的角度出发,定义不同的名称):
#grid { display: grid; grid-columns: "nav""first" 150px "content" 1fr "last"; grid-rows: "header" 50px "content" 1fr "footer" 50px; }
在元素上可以引用这些名称:
#menu { grid-column: "nav"; grid-row: "content"; } #header { grid-column: "content"; grid-row: "header"; } #article { grid-column: "content"; grid-row: "content"; }
还有一个规范,预先命名了四个网格线名称——垂直和水平方现的start和end,实际上他们构建了整个网格。例如,导航菜单在第一列,从第一行到最后一行,而footer元素从第二列到最后一列,不需要统计有多少行和多少列,就可以实现。
#menu { grid-column: 1; grid-row: start end; } #footer { grid-column: 2 end; grid-row: 3; }
单元格和模板命名
将来还有另一个方法,可以给单元格根据模板元素名称命名,用以创建一个虚拟结构模板:
#grid { display: grid; grid-template: "ln""ma""ba""ff"; grid-columns: auto minmax(min-content, 1fr); grid-rows: auto minmax(min-content, 1fr) auto auto; }
因此,将一个元素绑定到一个或另一个虚拟的网格中也可以使用这样的规则:
#article { grid-cell: "a"; }
如果根据不同的条件,比如说根据屏幕分辨率改变元素的位置,甚至改变网格本身。那么这种方法是很爽的:
@media (orientation: portrait) { #grid { display: grid; grid-template: "ln""ma""ba""ff"; grid-columns: auto minmax(min-content, 1fr); grid-rows: auto minmax(min-content, 1fr) auto auto; } } @media (orientation: landscape) { #grid { display: grid; grid-template: "ln""ma""mb""sf"; grid-columns: auto minmax(min-content, 1fr); grid-rows: auto minmax(min-content, 1fr) auto auto; } } #a grid-cell: "a"; }
注意,本文用来命名单元格的名称不会改变。(虽然现在还无法使用这些属性,但我们会等到浏览器支持这些特性)。
总结
在这篇文章中,我想尝试给大家介绍CSS3网格布局模块关键部分。我希望可以激励大家知道的比我多。
我将提醒大家,模块在不断的更新,W3C组织在不断的收集评论和修改意见。在Internet Explorer 10中可以看到一些基本功能的实现。这里提供了几个有兴的例子:ietestdrive.com:The Grid System和Hands On: CSS3 Grid Layout。
我也会继续观注CSS3网格布局模块的更新,现在支持网格布局模块的游览器只有IE10,也有可能将来会使用网格布局模块和HTML/JS来开发Windows8的Metro风格。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载烦请注明出处:
英文原文:http://www.splashnology.com/article/introduction-into-css3-grid-layout-workingwith-grids/5762/
中文译文:http://www.w3cplus.com/css3/introduction-into-css3-grid-layout.html