本文由大漠根据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 { width: 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</div> <div class="box grid40">40</div> <div class="box grid41">41</div> <div class="box grid42">42</div> <div class="box grid43">43</div> <div class="box grid44">44</div> <div class="box grid45">44</div> </div>LESS代码
Grid Less
.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; }调用的LESS
/* the values below are wrapped with ~"" in order to not break the LESS compiler */ .wrapper { width: 90%; margin: 0 auto 0 auto; display: ~"-ms-grid"; -ms-grid-columns:~" 1fr (4.25fr 1fr)[16]"; -ms-grid-rows:~" (auto 20px)[9]"; } /* this is an example of positioning items on the grid first row, single column items */ .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } .grid3 { .position(3,1,1,1); } .grid4 { .position(4,1,1,1); } .grid5 { .position(5,1,1,1); } .grid6 { .position(6,1,1,1); } .grid7 { .position(7,1,1,1); } .grid8 { .position(8,1,1,1); } .grid9 { .position(9,1,1,1); } .grid10 { .position(10,1,1,1); } .grid11 { .position(11,1,1,1); } .grid12 { .position(12,1,1,1); } .grid13 { .position(13,1,1,1); } .grid14 { .position(14,1,1,1); } .grid15 { .position(15,1,1,1); } .grid16 { .position(16,1,1,1); } /* second row items span 2 columns and one gutter */ .grid17 { .position(1,2,2,1); } .grid18 { .position(3,2,2,1); } .grid19 { .position(5,2,2,1); } .grid20 { .position(7,2,2,1); } .grid21 { .position(9,2,2,1); } .grid22 { .position(11,2,2,1); } .grid23 { .position(13,2,2,1); } .grid24 { .position(15,2,2,1); } /* third row we have 4 items spanning 3 cols and 1 spanning 4 */ .grid25 { .position(1,3,3,1); } .grid26 { .position(4,3,3,1); } .grid27 { .position(7,3,3,1); } .grid28 { .position(10,3,3,1); } .grid29 { .position(13,3,4,1); } /* fourth row 4 items spanning 4 columns each */ .grid30 { .position(1,4,4,1); } .grid31 { .position(5,4,4,1); } .grid32 { .position(9,4,4,1); } .grid33 { .position(13,4,4,1); } /* now let's get a little crazy ... */ .grid34 { .position(1,5,1,1); } .grid35 { .position(1,6,1,1); } .grid36 { .position(1,7,1,1); } .grid37 { .position(1,8,1,1); } .grid38 { .position(11,5,6,4); } .grid39 { .position(6,5,1,2); } .grid40 { .position(6,7,2,2); } .grid41 { .position(2,5,4,4); } .grid42 { .position(8,8,3,1); } .grid43 { .position(8,5,3,3); } .grid44 { .position(7,5,1,1); } .grid45 { .position(7,6,1,1); }转译出来的CSS
.wrapper { width: 90%; margin: 0 auto 0 auto; display: -ms-grid; -ms-grid-columns: 1fr (4.25fr 1fr)[16]; -ms-grid-rows: (auto 20px)[9]; } .grid1 { -ms-grid-column: 2; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid2 { -ms-grid-column: 4; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid3 { -ms-grid-column: 6; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid4 { -ms-grid-column: 8; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid5 { -ms-grid-column: 10; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid6 { -ms-grid-column: 12; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid7 { -ms-grid-column: 14; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid8 { -ms-grid-column: 16; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid9 { -ms-grid-column: 18; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid10 { -ms-grid-column: 20; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid11 { -ms-grid-column: 22; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid12 { -ms-grid-column: 24; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid13 { -ms-grid-column: 26; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid14 { -ms-grid-column: 28; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid15 { -ms-grid-column: 30; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid16 { -ms-grid-column: 32; -ms-grid-row: 1; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid17 { -ms-grid-column: 2; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid18 { -ms-grid-column: 6; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid19 { -ms-grid-column: 10; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid20 { -ms-grid-column: 14; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid21 { -ms-grid-column: 18; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid22 { -ms-grid-column: 22; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid23 { -ms-grid-column: 26; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid24 { -ms-grid-column: 30; -ms-grid-row: 3; -ms-grid-column-span: 3; -ms-grid-row-span: 1; } .grid25 { -ms-grid-column: 2; -ms-grid-row: 5; -ms-grid-column-span: 5; -ms-grid-row-span: 1; } .grid26 { -ms-grid-column: 8; -ms-grid-row: 5; -ms-grid-column-span: 5; -ms-grid-row-span: 1; } .grid27 { -ms-grid-column: 14; -ms-grid-row: 5; -ms-grid-column-span: 5; -ms-grid-row-span: 1; } .grid28 { -ms-grid-column: 20; -ms-grid-row: 5; -ms-grid-column-span: 5; -ms-grid-row-span: 1; } .grid29 { -ms-grid-column: 26; -ms-grid-row: 5; -ms-grid-column-span: 7; -ms-grid-row-span: 1; } .grid30 { -ms-grid-column: 2; -ms-grid-row: 7; -ms-grid-column-span: 7; -ms-grid-row-span: 1; } .grid31 { -ms-grid-column: 10; -ms-grid-row: 7; -ms-grid-column-span: 7; -ms-grid-row-span: 1; } .grid32 { -ms-grid-column: 18; -ms-grid-row: 7; -ms-grid-column-span: 7; -ms-grid-row-span: 1; } .grid33 { -ms-grid-column: 26; -ms-grid-row: 7; -ms-grid-column-span: 7; -ms-grid-row-span: 1; } .grid34 { -ms-grid-column: 2; -ms-grid-row: 9; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid35 { -ms-grid-column: 2; -ms-grid-row: 11; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid36 { -ms-grid-column: 2; -ms-grid-row: 13; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid37 { -ms-grid-column: 2; -ms-grid-row: 15; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid38 { -ms-grid-column: 22; -ms-grid-row: 9; -ms-grid-column-span: 11; -ms-grid-row-span: 7; } .grid39 { -ms-grid-column: 12; -ms-grid-row: 9; -ms-grid-column-span: 1; -ms-grid-row-span: 3; } .grid40 { -ms-grid-column: 12; -ms-grid-row: 13; -ms-grid-column-span: 3; -ms-grid-row-span: 3; } .grid41 { -ms-grid-column: 4; -ms-grid-row: 9; -ms-grid-column-span: 7; -ms-grid-row-span: 7; } .grid42 { -ms-grid-column: 16; -ms-grid-row: 15; -ms-grid-column-span: 5; -ms-grid-row-span: 1; } .grid43 { -ms-grid-column: 16; -ms-grid-row: 9; -ms-grid-column-span: 5; -ms-grid-row-span: 5; } .grid44 { -ms-grid-column: 14; -ms-grid-row: 9; -ms-grid-column-span: 1; -ms-grid-row-span: 1; } .grid45 { -ms-grid-column: 14; -ms-grid-row: 11; -ms-grid-column-span: 1; -ms-grid-row-span: 1; }从代码中再一次可以看出,如果使用css直接写grid,不但代码量增加了,现且还要进行一些数学计算,说不定哪一下不小心就绕进去了。使用LESS可减少了不少的麻烦。
——大漠
媒体查询与网格
这个示例和前面的示例使用完全相同的标记。然而,我们现在使用媒体查询检测屏幕宽度和根据不同的宽度使用不同的列数重新定义网格。
我开始先在“.wrapper”容器上定义了一个6列的网格,然后设置不同的项目在这个网格上:
.wrapper { width: 90%; margin: 0 auto 0 auto; display: ~"-ms-grid"; /* escaped for the LESS parser */ -ms-grid-columns: ~"1fr (4.25fr 1fr)[6]"; /* escaped for the LESS parser */ -ms-grid-rows: ~"(auto 20px)[40]"; /* escaped for the LESS parser */ } .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } /* ... see example for all declarations ... */
全部LESS代码
.wrapper { width: 90%; margin: 0 auto 0 auto; display: ~"-ms-grid"; -ms-grid-columns: ~"1fr (4.25fr 1fr)[6]"; -ms-grid-rows: ~"(auto 20px)[16]"; } /* this is an example of positioning items on the 6 column grid first row, single column items */ .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } .grid3 { .position(3,1,1,1); } .grid4 { .position(4,1,1,1); } .grid5 { .position(5,1,1,1); } .grid6 { .position(6,1,1,1); } /* second row, single column items */ .grid7 { .position(1,2,1,1); } .grid8 { .position(2,2,1,1); } .grid9 { .position(3,2,1,1); } .grid10 { .position(4,2,1,1); } .grid11 { .position(5,2,1,1); } .grid12 { .position(6,2,1,1); } /* third row, four single column items and a 2 column item - lets display the wide one in the middle */ .grid13 { .position(1,3,1,1); } .grid14 { .position(2,3,1,1); } .grid15 { .position(5,3,1,1); } .grid16 { .position(6,3,1,1); } .grid17 { .position(3,3,2,1); } /* fourth row - three two column items */ .grid18 { .position(1,4,2,1); } .grid19 { .position(3,4,2,1); } .grid20 { .position(5,4,2,1); } /* fifth row - three two column items */ .grid21 { .position(1,5,2,1); } .grid22 { .position(3,5,2,1); } .grid23 { .position(5,5,2,1); } /* sixth row - a two column item and a four column item */ .grid24 { .position(1,6,2,1); } .grid29 { .position(3,6,4,1); } /* seventh and eigth row we have 4 items spanning 3 cols */ .grid25 { .position(1,7,3,1); } .grid26 { .position(4,7,3,1); } .grid27 { .position(1,8,3,1); } .grid28 { .position(4,8,3,1); } /* ninth, tenth and eleventh rows */ .grid30 { .position(1,9,3,1); } .grid31 { .position(4,9,3,1); } .grid32 { .position(1,10,6,1); } .grid33 { .position(1,11,6,1); } /* now let's get a little crazy ... */ .grid34 { .position(1,12,1,1); } .grid35 { .position(1,13,1,1); } .grid36 { .position(1,14,1,1); } .grid37 { .position(1,15,1,1); } .grid38 { .position(1,16,1,1); } .grid39 { .position(1,17,1,1); } .grid40 { .position(2,12,5,2); } .grid41 { .position(2,14,3,1); } .grid42 { .position(5,14,2,1); } .grid43 { .position(5,15,2,2); } .grid44 { .position(5,17,2,1); } .grid45 { .position(2,15,3,3); }
使用媒体查询,当我们触及屏幕最小宽度为700像素时,重新定义网格为九列。
@media only screen and (min-width: 700px) { .wrapper { -ms-grid-columns: ~"1fr (4.25fr 1fr)[9]"; -ms-grid-rows: ~"(auto 20px)[50]"; } .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } /* ... */ }
全部LESS代码
@media only screen and (min-width: 700px) { .wrapper { -ms-grid-columns: ~"1fr (4.25fr 1fr)[9]"; -ms-grid-rows: ~"(auto 20px)[10]"; } /* we now have nine columns to play with first row, single column items */ .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } .grid3 { .position(3,1,1,1); } .grid4 { .position(4,1,1,1); } .grid5 { .position(5,1,1,1); } .grid6 { .position(6,1,1,1); } .grid7 { .position(7,1,1,1); } .grid8 { .position(8,1,1,1); } .grid9 { .position(9,1,1,1); } /* second row */ .grid10 { .position(1,2,1,1); } .grid11 { .position(2,2,1,1); } .grid12 { .position(3,2,1,1); } .grid13 { .position(4,2,1,1); } .grid14 { .position(7,2,1,1); } .grid15 { .position(8,2,1,1); } .grid16 { .position(9,2,1,1); } .grid17 { .position(5,2,2,1); } /* third row items span 2 columns and one gutter */ .grid18 { .position(1,3,2,1); } .grid19 { .position(3,3,2,1); } .grid20 { .position(5,3,1,1); } .grid21 { .position(6,3,2,1); } .grid22 { .position(8,3,2,1); } /* fourth row */ .grid23 { .position(1,4,2,1); } .grid24 { .position(8,4,2,1); } .grid25 { .position(3,4,3,1); } .grid26 { .position(6,4,2,1); } /* fifth row */ .grid27 { .position(1,5,3,1); } .grid28 { .position(4,5,3,1); } .grid29 { .position(7,5,3,1); } /* sixth and seventh row */ .grid30 { .position(1,6,4,1); } .grid31 { .position(5,6,5,1); } .grid32 { .position(1,7,5,1); } .grid33 { .position(6,7,4,1); } /* now let's get a little crazy ... */ .grid34 { .position(1,8,1,1); } .grid35 { .position(1,9,1,1); } .grid36 { .position(1,10,1,1); } .grid37 { .position(1,11,1,1); } .grid38 { .position(1,12,1,1); } .grid39 { .position(2,11,8,2); } .grid40 { .position(2,8,2,2); } .grid41 { .position(4,8,4,3); } .grid42 { .position(2,10,2,1); } .grid43 { .position(8,8,1,1); } .grid44 { .position(9,8,1,3); } .grid45 { .position(8,9,1,2); } }
最后,我们重新定义网格为960像素,回到我们前面定义的16列网格。
@media only screen and (min-width: 940px) { .wrapper { -ms-grid-columns:~" 1fr (4.25fr 1fr)[16]"; -ms-grid-rows:~" (auto 20px)[24]"; } .grid1 { .position(1,1,1,1); } .grid2 { .position(2,1,1,1); } /* ... */ }
如果你在IE10下查看示例可以看出网格可以适应窗口大小做一定的回来变化。您还可以看到,看到最后的组块,源顺序已无关紧要。你可以从任何地方拿起一块并将其放置在网格上的任何位置。
制作一个简单的网站布局
到目前为止,我们一直都只在玩这些盒子块,并没有考虑在这些盒子块中放什么东西。所以让我们来看看一个更现实的布局,为了明白什么是CSS3网格布局模块是非常有用的。我们要做一个网站,类似于下面这样的布局。
因为我使用CSS3网格布局,我可以控制我的源代码的逻辑顺序。尽管这些元素可以以任何顺序展示,在这个示例中文档流按照下面的方式。
<div class="wrapper"> <div class="welcome"> ... </div> <article class="main"> ... </article> <div class="info"> ... </div> <div class="ads"> ... </div> </div>
在宽度的视窗下,我们可以用网格创建一个侧边栏,把重要的信息(比如开放时间)放在侧边栏顶部,把广告放在它的下面。创建布局的代码如下:
@media only screen and (min-width: 940px) { .wrapper { -ms-grid-columns:~" 1fr (4.25fr 1fr)[16]"; -ms-grid-rows:~" (auto 20px)[24]"; } .welcome { .position(1,1,12,1); padding: 0 5% 0 0; } .info { .position(13,1,4,1); border: 0; padding:0; } .main { .position(1,2,12,1); padding: 0 5% 0 0; } .ads { .position(13,2,4,1); display: block; margin-left: 0; } }
在一个浮动布局中,这样一个侧边栏在较小屏幕宽度下,通常被放置在主要内容下面。对于我来说,这是不理想的。我想重要的信息(开放时间)、主要文章放上面,把广告放在下面。在小屏幕宽度下,使用网格布局可以很容易实现这个布局。“.info”占两行和“.ads”在第五行,两者之间就是主要文章。
.wrapper { display: ~"-ms-grid"; -ms-grid-columns: ~"1fr (4.25fr 1fr)[4]"; -ms-grid-rows: ~"(auto 20px)[40]"; } .welcome { .position(1,1,4,1); } .info { .position(1,2,4,1); border: 4px solid #fff; padding: 10px; } .content { .position(1,3,4,5); } .main { .position(1,3,4,1); } .ads { .position(1,4,4,1); }
最后,作为一个额外的调整,我增加了一个断点在600像素处广告区域嵌套了第二个网格,让这三个图像在一行排列。
@media only screen and (min-width: 600px) { .ads { display: ~"-ms-grid"; -ms-grid-columns: ~"20px 1fr 20px 1fr 20px 1fr"; -ms-grid-rows: ~"1fr"; margin-left: -20px; } .ad:nth-child(1) { .position(1,1,1,1); } .ad:nth-child(2) { .position(2,1,1,1); } .ad:nth-child(3) { .position(3,1,1,1); } }
这是一个非常简单的例子,展示了我们如何使用CSS3网格布局而不需要在文档中添加大量的类来实现这个布局。它还演示了,如何根据不同的屏幕,让用户查看主要的内容。
布局、源顺序和内容优先的想法
CSS3网格布局并不是唯一的模块,能让我们的视觉布局远离源秩序。然而在IE10中得到良好的支持,这是一个很好的开始。如果你看看网格布局模块,是否有可能与Flexbox布局模块以及很有趣的CSS regions和exclusions规范结合在一起。如果可以,那么让人很兴奋的,我们将拥有史上最强大的布局工具。
我特别热衷于源秩序从布局中分离,而不是相吻合,这样我就不需要花太多的时间去思考,布局和秩序的相互吻合。作为一个CMS开发人员,在开发大型项目,正如我们的CMS产品Perch,我更关注的是通过内容编辑器来创建网页。特别是,我寻找更好的方法来帮助他们创建自适应内容。这个内容将工作在种语镜下,而不是被绑定到一个表示的内容。
如果适应内容概念对你来说是刚接触的,你可以看看Karen McGrane的演讲:Adapting Ourselves to Adaptive Content。Karen谈到了需要的内容块,可以用在许多不同的地方,显示不同的上下文。
我绝对同意Karen介绍的内容。我们一直试图移动内容编辑远离考虑创建一上页面并在它的桌面上预览。然而在某种程度上的内容不需要发布成一个页面,或者你愿意将少量收集的内容优先发布。尤其是在小屏幕上下文,内容得到限制,我们可显示只能这么多,这样我们就需要确保重要内容排到顶部。对于我的例子,我想确保地址信息不要滚动太多内容就清晰可见。让他和整个侧栏放到页面底部并不会有太大的作用,尽管整个栏目都移动到屏幕的顶部,这样用户需要滚动广告才能看到文章。
如果我们的布局要和源顺序一样,那么使用内容编辑来决定优先级是很困难的。只有一个系统可以做一些源顺序更新——或许通过多个模板来实现。对于更大的系统中,这可能是一种可能性;对于小规模或者使用较小的CMS,它不大可能。幸运的是,任何系统,允许某种形式的自定义字段,给元素绑定一个类名,并使用CSS3的网格布局,就能将锁定的元素拖动放到正确的地方,让内容在台式电脑桌面或移动设置上显示。
这种方法可以让我们远离让编辑器来思考视觉上的效果。目前,我可能需要解释一个编辑,如果某个内容在移动设备上需要先来观看时,它需要放在侧边栏区域,有一个特定的布局和设计。我必须这么做,因为我们不得不执行相当严格规定的源顺序,以便使用responsive设计。如果我可以建议一个编辑器可以把重要的内容设置一个标记,如CMS中高优先级。然后我可以在其他地方做决定——如何显示,我们可以保持视觉层次结构方式,用不同的方法呈现内容。
为什么规范特性不能用于生产中?
当前工作的CSS工作组中CSS3网格布局规范在被列在了工作草案部分的列表中。如果我们在生产中不能使用它,我们在这个阶段讨论这个模块似乎有点无意义,但这样做是一个非常现实的理想。如果我们想能够更大的在开发网站使用这个工具,那么我们可以开始给w3c规范反馈一些重要的信息。如果你感兴趣,你可以在这里参加讨论。
所以,如果你有一点时间,为什么没有玩一下CSS3网格布局模块呢?这里我列出了我的一些想法和其他模块的网格布局,我们可以更改源顺序制作一些布局。同样,无论你是在工作还是玩,都可以思考这个新规范,想想如何使用它们来增强你的工作。发现一个问题吗?认为改变规范将改善的一些事情?然后你有事情,你可以发布到www-style网站添加一个讨论模块,进行讨论。
本文所有示例都在CodePen上可以查阅,并且修改他们。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
如需转载烦请注明出处:
英文原文:http://24ways.org/2012/css3-grid-layout
中文译文:http://www.w3cplus.com/css3/css3-grid-layout-module.html