使用CSS3 Grid布局实现内容优先
本文由大漠根据Rachel Andrew的《Giving Content Priority with CSS3 Grid Layout》所译,整个译文带有我们自己的理解与思想,如果译得不好或不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://24ways.org/2012/css3-grid-layout,以及作者相关信息
——作者:Rachel Andrew
——译者:大漠
浏览器支持许多CSS3的模块,帮助我们解决我们习惯于使用图片的CSS效果。崛起的移动浏览器和响应式网页设计概念给了我们一个全新的方式来来看待Web设计。然而,当它们来临的时候,我们的布局还没有跟上。我们已经讨论了多年的源顺序、内容也结构和内容与样式的分离。然而,为了得到一定的视觉布局,我们大多数不得不决定源秩序。
目前,W3C在制作一些一趣的规范,虽然这些规范会不断的变化,但他们总是在一个起跑线上变动。在这篇文章中,我将向大家介绍CSS的一个模块——CSS3网格布局模块,使我们能够定义一下网格和放置元素。本文实示演示基本的网格布局,并讨一个方法,我们可以开始思考的内容是具有一个更多的自适应方法。
在我们开始之前,需要特别注意,在撰写本文的时候,这些例子只能在IE10上运行。CSS3网格布局是由微软创建的一个模块,在使用的时候需要添加IE10浏览器的前缀“-ms-”。我的例子都将使用“-ms-”前缀,而不包括其他浏览器的前缀,不仅仅因为CSS3 Grid布局模块还是一个规范草案,而且在其他浏览器中实现的效果也可能存在不一致。实现今天的效果也很有可能会改变,希望能得到您的反馈。
如果你还没有IE10浏览器,你可以先到Browserstack注册一个账号——可以免费试用看看。我也把相关阶段的示例截图放在文章中展示。
什么是CSS3 Grid布局?
CSS3网格布局目的是让开发人员设计一个网格并将内容放在这些网格内。而不是使用浮动制作一个网格,实际上你将一个元素声明为一个网格容器,并把元素内容置于网格中。最重要的是文档流的源顺序并不重要。
声明网格
我们声明一个网格是使用“display”的新属性值:“display:grid”。由于我们这里需要在IE10中实现,所以我们需要加上前缀:“display:-ms-grid;”。
一旦我们声明了网格,就可以使用“grid-columns”和“grid-rows”属性来设置列与行。
.wrapper {
display: -ms-grid;
-ms-grid-columns: 200px 20px auto 20px 200px;
-ms-grid-rows: auto 1fr;
}
在上面的示例中,把“.wrapper”元素声明成一个网格。我使用“grid-columns”属性创建了一个200像素宽度的列,一个20像素的间距,一个根据可用空间的弹性列,另一个20像素的间距和200像素的侧边栏:一个灵活的布局有两个固定宽度的侧边栏。使用“grid-rows”属性我创建了两行:第一行设置了“auto”,不管是否入内容他都将延伸填允;第二行设置了“1fr”,一个用于网格的新单位值,他意味着一个分数单位。在这种情况之下,一个分数单位的可用空间,不管空间是否存在都是有效的。
网格项目定位
现在有一个简单的网格,我需要把内容放上去。假如我有一个类名叫“.mian”的div,我想把他放在网格的第二行和设置了auto值的列,我可以使用下面的样式:
.main {
-ms-grid-column: 3;
-ms-grid-row: 2;
-ms-grid-row-span: 1;
}
如果你是一个老的开发人员,你可能已经意识到,我们其实是使用CSS创建了一个类似于HTML的表格布局。如果你想尝试找到对应的元素,你可以把网格布局当作一个表格的概念,这是最有益的方法。
创建网格系统
当我们开始玩CSS3网格布局时,我想看看我能否用它来复制一个类似于960流体16列网格系统这样的一个灵活的网格系统。
我先把容器wrapper元素定义成一个网格容器,使用分数让这个网格变成流体网格。
.wrapper {
90%;
margin: 0 auto 0 auto;
display: -ms-grid;
-ms-grid-columns: 1fr (4.25fr 1fr)[16];
-ms-grid-rows: (auto 20px)[24];
}
我举的实例类似于960网格系统。网格每一列前后有一个间距,然后按这样的方式重复16次。这就意味着,如果我想要跨越两列,在网格布局模块中而言,实际上是跨越了三个列:两个单元格再加上一个间距。所在在项目定位时要明确指定。
我为每个定位选项创建了一个类名:列、行和间距,例如:
.grid1 {-ms-grid-column: 2;} /* applying this class positions an item in the first column (the gutter is column 1) */
.grid2 {-ms-grid-column: 4;} /* 2nd column - gutter|column 1|gutter */
.grid3 {-ms-grid-column: 6;} /* 3rd column - gutter|column 1|gutter|column2|gutter */
.row1 {-ms-grid-row:1;}
.row2 {-ms-grid-row:3;}
.row3 {-ms-grid-row:5;}
.colspan1 {-ms-grid-column-span:1;}
.colspan2 {-ms-grid-column-span:3;}
.colspan3 {-ms-grid-column-span:5;}
我可以为每个元素添加多类名用来设置元素在网格上的位置。
我使用CSS3网格布局复制的一个流体网格。请启用IE10,才能正常浏览这个示例。
可以工作,但...
这个可以工作,但并不理想。我认为我的测试在这个阶段是不显示,然而,我认为它清楚的显示了网格布局模块工作的特点,这是一个有用的开始。不过,这在生产中这也不是一个方法。首先我们必须对我们的标记定义类名,然后定位到一个网格的位置上。如果我们总是要操持16列网格,这可能不是太大的问题。我将告诉你,真正强大的网格布局模块是基于不同的媒体查询使用网格布局,他自己就能开始重新定义网格。如果在小显屏下使用6列布局,那么16列网格定位元素就没有任何的意义。
使用LESS定义网格的位置
正如我们所看到的,如果你想使用一个主列和间距定义一个网格,你必须考虑到列间距和一个实际列。这就意味着,我们为每一个项目上网格都不得不做一些计算。在上面的示例中,为每个位置创建了一个类名,让我觉得我们应该是在16列内而不是32列。但通过使用CSS预处理程序,我们可以避免使用所有列,只要认为是在主列中。
在我的示例中,我使用了LESS。 我的简单网格框架由一个简单的mixin来完成。
/*----------------------------------------------------------------*
* 1、使用LESS定义一个mixin,名叫.position,定义方法类似定义一个类
* 2、 @column定义列
* 3、 @row定义行
* 4、 @colspan跨越的列
* 5、 @rowspan跨越的行
*----------------------------------------------------------------*/
.position(@column,@row,@colspan,@rowspan) {
-ms-grid-column: @column*2;
-ms-grid-row: @row*2-1;
-ms-grid-column-span: @colspan*2-1;
-ms-grid-row-span: @rowspan*2-1;
}
我的mixin包含四个参数:列、行、跨越的列和跨越的行。如果我想把一个项目放在列四、行三、跨越两个列和一行。我们可以像下面一样写CSS样式:
.box { .position(4,3,2,1); }
mixin转译出来:
.box {
-ms-grid-column: 8;
-ms-grid-row: 5;
-ms-grid-column-span: 3;
-ms-grid-row-span: 1;
}
这样让我们少打很多字与做一些数学计算。也可以添加浏览器的前缀到mixin中,就像一开始就做了浏览器兼容处理。
我们可以看到,这回创建了一个新的网格。不是对每个元素添加多个类,而是添加一个类,这个类使用了mixin创建需要的位置。我一直在mixin中使用跨行,你可以看到我最后制作了一个相当复杂的网格布局。我使用了JavaScrpt LESS解析器,这样您就可以查看我使用的LESS。注意,为了避免使用-ms的前缀,在LESS代码中实际使用了“~”来代替。
看起来很棒。在模板中没有为每个元素定认指定太多信息,我仅用了一个类名——grid(x),但可能会有更符合语义化地类名。我们现在可以进一步的扩展这个例子,就是根据屏幕宽度重新定义网格。
示例代码
为了节省大家的时间,我特意将其代码扣出放在这里,以供大家参考:
HTML结构
<div class="wrapper"> <div class="box grid1">01</div> <div class="box grid2">02</div> <div class="box grid3">03</div> <div class="box grid4">04</div> <div class="box grid5">05</div> <div class="box grid6">06</div> <div class="box grid7">07</div> <div class="box grid8">08</div> <div class="box grid9">09</div> <div class="box grid10">10</div> <div class="box grid11">11</div> <div class="box grid12">12</div> <div class="box grid13">13</div> <div class="box grid14">14</div> <div class="box grid15">15</div> <div class="box grid16">16</div> <div class="box grid17">17</div> <div class="box grid18">18</div> <div class="box grid19">19</div> <div class="box grid20">20</div> <div class="box grid21">21</div> <div class="box grid22">22</div> <div class="box grid23">23</div> <div class="box grid24">24</div> <div class="box grid25">25</div> <div class="box grid26">26</div> <div class="box grid27">27</div> <div class="box grid28">28</div> <div class="box grid29">29</div> <div class="box grid30">30</div> <div class="box grid31">31</div> <div class="box grid32">32</div> <div class="box grid33">33</div> <div class="box grid34">34</div> <div class="box grid35">35</div> <div class="box grid36">36</div> <div class="box grid37">37</div> <div class="box grid38">38</div> <div class="box grid39">39