5.4 多行多栏布局

本章最后,为了给第7章设计完整的网页做好准备,我们要把前面学习的三栏布局的技术付诸实用。我准备向大家展示一个更复杂,也更接近实际的页面框架。这个页面的布局可以用作WordPress模板或一个公司网站的基础。

前面的布局中只包含一个article、一个nav……,因此比较容易选择,只要用标签名即可。而在创建复杂布局时,一个页面中会出现多个相同的标签,选择的时候就要用上下文选择符来区分它们了。我想通过下面的例子,告诉你怎么给标记中添加最少的ID和类,同时精确地选择任意元素。

本章前面说过,使用CSS3的box-sizing:border-box声明,可以避免利用内部div为内容添加边距。可是,这些内部元素,无论是div还是别的什么元素,也能辅助添加各种样式,这个例子会展示它们在这方面的用途。

这个布局(如图5-13所示)由六个等宽的行组成,其中第四行有三栏,第五行有四栏。

enter image description here图5-13 包含六个等宽行和两组不同分栏的布局

这个布局的标记如下。

  1. <div id="wrapper">
  2. <header>
  3. <h1>Full-width content</h1>
  4. </header>
  5. <nav>
  6. <p>Navigation menus go here</p>
  7. </nav>
  8. <section id="branding">
  9. <img src="images/grand_canyon.jpg" alt="Grand Canyon" />
  10. </section><!-- branding 结束 -->
  11. <section id="feature_area">
  12. <article>
  13. <div class="inner">
  14. <p>Lorem Ipsum text</p>
  15. </div>
  16. </article>
  17. <!-- 省略另外两个 article 元素 -->
  18. </section><!-- feature_area 结束-->
  19. <section id="promo_area">
  20. <article>
  21. <div class="inner">
  22. <p>Lorem Ipsum text</p>
  23. </div>
  24. </article>
  25. <!-- 省略另外三个 article 元素 -->
  26. </section><!-- promo_area 结束-->
  27. <footer>
  28. <p>A CSS template from <a href="http://www.stylinwithcss.com"><em>Stylin’ with CSS, Third Edition</em></a> by Charles Wyke-Smith</p>
  29. </footer>
  30. </div>

至于怎么把以上标记变成图5-13所示的布局,实际上我们都已经讲过了。比如,等宽的各行,不用设定它们的宽度,让它们自动扩展填充外包装元素即可。各个栏是由浮动元素构成的,为了防止布局变宽导致右边的栏“下滑”,不要给容器添加内边距,而是把水平内边距加到内部div上。是不是?这些你都知道了。与其再把那些CSS罗列一遍,不如专门讲几个特殊的CSS片段,看看要在包含上百个HTML元素的复杂标记中如何精确地选择元素。

本例完整的CSS代码,可以在本书网站下载:http://www.stylinwithcss.com

5.4.1 CSS选择符的实际应用

有必要的话,请读者自行参考第2章有关选择符的内容。

随着页面变得越来越复杂,相同的HTML元素(如sectionarticlenav,等等)会出现很多次——比如,前面布局中的article就出现了7次。为了选择某个元素,必须区分这些相同的标签名。为此,有些新手会给每个标签都添加一个不同的类名。但这种做法是不值得提倡的。不仅因为类本身就不该这么用(类应该用于标记具有相同特征的元素),而且这么多类会把标记弄得很乱,让CSS也很难看懂。为了知道每个类代表哪个元素,你必须不断地查看HTML。

更好的做法是给标记中每个主要区域的顶级元素添加一个ID,这也是使用ID的正确方式,ID就是标识页面中唯一元素用的。然后,这些ID就会成为HTML标记中的“路标”,放在上下文选择符开头的时候,它们就能起到框定后代元素的作用。这就是在标记中保持类和ID属性最少的秘诀。而且,相应的上下文选择符也能清晰地传达出路径信息,让人从CSS中一眼就能看出它要选择哪个元素。

英文中经常用hook(这里译为“路标”,也有译为“钩子”的),表示代码中一个唯一的参照点,其他代码通过这个参照点可以与相应的代码交互。

再看看前面的HTML标记。其中的三个ID是我精确选择任意元素唯一必要的几个“路标”,即使再给布局中添加一些内容元素,恐怕也用不着更多了,顶多再多几个。至于具体怎么使用它们,下面我就通过为第四行的栏添加边框来演示。

这一行的顶级元素是一个ID为feature_areasection。这个容器中包含三个article元素,分别作为一栏。下面来看看这一行的CSS。

  1. /*每个article作为一个浮动栏*/
  2. section#feature_area article {
  3. float:left;
  4. width:320px;
  5. /*对于作为栏的容器,只能添加垂直内边距*/
  6. padding:10px 0;
  7. background:#fff;
  8. border-top:4px solid #f7be84;
  9. }
  10. /*为所有内容盒子添加公共样式*/
  11. section#feature_area article .inner {
  12. margin:10px 20px;
  13. padding:5px;
  14. background:#fff;
  15. border:5px solid;
  16. }
  17. /*以下三条分别为三个内容盒子设定样式*/
  18. section#feature_area article:nth-child(1) .inner {
  19. border-color:#d7dd6f;
  20. }
  21. section#feature_area article:nth-child(2) .inner {
  22. border-color:#f6dec5;
  23. }
  24. section#feature_area article:nth-child(3) .inner {
  25. border-color:#d1d8e4;
  26. }

我用section#feature_area article选择了三个盒子,用一条规则声明了这些元素共有的样式,包括宽度、内边距、边框等。这样,对这三个盒子只需维护一组声明即可。

然后,通过三条规则分别为三个盒子设定独特的样式。下面就是为第二个内部div应用样式的规则:

  1. section#feature_area article:nth-child(2) .inner {
  2. border:5px solid #f6dec5;}

从后往前,这条规则的意思是:选择类为inner的元素,它必须是父元素中的第二个article,而且这个article必须包含在ID为feature_areasection元素中,将它的边框设定为淡橙色。

显然,只要顶级元素上有一个ID,我们就可以把它作为“路标”,进而选择它的任意后代元素(甚至能够选择将来才会加入其中的内容元素)。另外,同样重要的是,这样也避免了无意中把样式添加给标记中的其他元素上。如果在没有别的手段让你选择某个特定元素的情况下,只在标记中添加一个类或一个ID,那么HTML就能保持清晰整洁,而CSS也将易读易维护。

5.4.2 内部DIV实战

这个布局也非常恰当地演示了内部div承担的定位和样式这两个角色。具体来说,这个布局中的内部div不仅确保了水平内边距不会破坏布局,另外也承担了一个视觉功能——内容区的彩色边框就是它们的边框。它们的父元素article在页面中是看不到的,但为了让你看见,我临时给中间的article应用一个背景色,如图5-14所示。

enter image description here图5-14 中间的article元素拥有灰色背景

从中间带灰色背景的article元素可以看出,这一行中的三个article充满了容器元素section,而且彼此之间亲密无间。

再强调一次吧,每一栏中的间距要依靠内部div。这个例子中的水平间距是由内部div的左、右外边距生成的,它们把这个div压缩了一下,这才使内容远离了父元素article(如果此时直接给article元素应用水平内边距的话,一定会破坏布局)。而每一栏中的垂直间距是由父元素的内边距生成的。为什么要用父元素呢?原因前面也提到过,就是在父元素没有上、下边框的情况下,子元素的上、下外边距会折叠的。

到此为止,我们关于这个布局的讨论就告以段落了。相信读者对如何使用上下文选择符一定有了深刻的理解。等到第7章,我们还将以这个布局为基础,创造出不一样的设计。