5.4 多行多栏布局
本章最后,为了给第7章设计完整的网页做好准备,我们要把前面学习的三栏布局的技术付诸实用。我准备向大家展示一个更复杂,也更接近实际的页面框架。这个页面的布局可以用作WordPress模板或一个公司网站的基础。
前面的布局中只包含一个article
、一个nav
……,因此比较容易选择,只要用标签名即可。而在创建复杂布局时,一个页面中会出现多个相同的标签,选择的时候就要用上下文选择符来区分它们了。我想通过下面的例子,告诉你怎么给标记中添加最少的ID和类,同时精确地选择任意元素。
本章前面说过,使用CSS3的box-sizing:border-box
声明,可以避免利用内部div
为内容添加边距。可是,这些内部元素,无论是div
还是别的什么元素,也能辅助添加各种样式,这个例子会展示它们在这方面的用途。
这个布局(如图5-13所示)由六个等宽的行组成,其中第四行有三栏,第五行有四栏。
图5-13 包含六个等宽行和两组不同分栏的布局
这个布局的标记如下。
- <div id="wrapper">
- <header>
- <h1>Full-width content</h1>
- </header>
- <nav>
- <p>Navigation menus go here</p>
- </nav>
- <section id="branding">
- <img src="images/grand_canyon.jpg" alt="Grand Canyon" />
- </section><!-- branding 结束 -->
- <section id="feature_area">
- <article>
- <div class="inner">
- <p>Lorem Ipsum text</p>
- </div>
- </article>
- <!-- 省略另外两个 article 元素 -->
- </section><!-- feature_area 结束-->
- <section id="promo_area">
- <article>
- <div class="inner">
- <p>Lorem Ipsum text</p>
- </div>
- </article>
- <!-- 省略另外三个 article 元素 -->
- </section><!-- promo_area 结束-->
- <footer>
- <p>A CSS template from <a href="http://www.stylinwithcss.com"><em>Stylin’ with CSS, Third Edition</em></a> by Charles Wyke-Smith</p>
- </footer>
- </div>
至于怎么把以上标记变成图5-13所示的布局,实际上我们都已经讲过了。比如,等宽的各行,不用设定它们的宽度,让它们自动扩展填充外包装元素即可。各个栏是由浮动元素构成的,为了防止布局变宽导致右边的栏“下滑”,不要给容器添加内边距,而是把水平内边距加到内部div
上。是不是?这些你都知道了。与其再把那些CSS罗列一遍,不如专门讲几个特殊的CSS片段,看看要在包含上百个HTML元素的复杂标记中如何精确地选择元素。
本例完整的CSS代码,可以在本书网站下载:http://www.stylinwithcss.com。
5.4.1 CSS选择符的实际应用
有必要的话,请读者自行参考第2章有关选择符的内容。
随着页面变得越来越复杂,相同的HTML元素(如section
、article
、nav
,等等)会出现很多次——比如,前面布局中的article
就出现了7次。为了选择某个元素,必须区分这些相同的标签名。为此,有些新手会给每个标签都添加一个不同的类名。但这种做法是不值得提倡的。不仅因为类本身就不该这么用(类应该用于标记具有相同特征的元素),而且这么多类会把标记弄得很乱,让CSS也很难看懂。为了知道每个类代表哪个元素,你必须不断地查看HTML。
更好的做法是给标记中每个主要区域的顶级元素添加一个ID,这也是使用ID的正确方式,ID就是标识页面中唯一元素用的。然后,这些ID就会成为HTML标记中的“路标”,放在上下文选择符开头的时候,它们就能起到框定后代元素的作用。这就是在标记中保持类和ID属性最少的秘诀。而且,相应的上下文选择符也能清晰地传达出路径信息,让人从CSS中一眼就能看出它要选择哪个元素。
英文中经常用hook(这里译为“路标”,也有译为“钩子”的),表示代码中一个唯一的参照点,其他代码通过这个参照点可以与相应的代码交互。
再看看前面的HTML标记。其中的三个ID是我精确选择任意元素唯一必要的几个“路标”,即使再给布局中添加一些内容元素,恐怕也用不着更多了,顶多再多几个。至于具体怎么使用它们,下面我就通过为第四行的栏添加边框来演示。
这一行的顶级元素是一个ID为feature_area
的section
。这个容器中包含三个article
元素,分别作为一栏。下面来看看这一行的CSS。
/*每个article作为一个浮动栏*/
section#feature_area article {
float:left;
width:320px;
/*对于作为栏的容器,只能添加垂直内边距*/
padding:10px 0;
background:#fff;
border-top:4px solid #f7be84;
}
/*为所有内容盒子添加公共样式*/
section#feature_area article .inner {
margin:10px 20px;
padding:5px;
background:#fff;
border:5px solid;
}
/*以下三条分别为三个内容盒子设定样式*/
section#feature_area article:nth-child(1) .inner {
border-color:#d7dd6f;
}
section#feature_area article:nth-child(2) .inner {
border-color:#f6dec5;
}
section#feature_area article:nth-child(3) .inner {
border-color:#d1d8e4;
}
我用section#feature_area article
选择了三个盒子,用一条规则声明了这些元素共有的样式,包括宽度、内边距、边框等。这样,对这三个盒子只需维护一组声明即可。
然后,通过三条规则分别为三个盒子设定独特的样式。下面就是为第二个内部div
应用样式的规则:
section#feature_area article:nth-child(2) .inner {
border:5px solid #f6dec5;}
从后往前,这条规则的意思是:选择类为inner
的元素,它必须是父元素中的第二个article
,而且这个article
必须包含在ID为feature_area
的section
元素中,将它的边框设定为淡橙色。
显然,只要顶级元素上有一个ID,我们就可以把它作为“路标”,进而选择它的任意后代元素(甚至能够选择将来才会加入其中的内容元素)。另外,同样重要的是,这样也避免了无意中把样式添加给标记中的其他元素上。如果在没有别的手段让你选择某个特定元素的情况下,只在标记中添加一个类或一个ID,那么HTML就能保持清晰整洁,而CSS也将易读易维护。
5.4.2 内部DIV实战
这个布局也非常恰当地演示了内部div
承担的定位和样式这两个角色。具体来说,这个布局中的内部div
不仅确保了水平内边距不会破坏布局,另外也承担了一个视觉功能——内容区的彩色边框就是它们的边框。它们的父元素article
在页面中是看不到的,但为了让你看见,我临时给中间的article
应用一个背景色,如图5-14所示。
图5-14 中间的article
元素拥有灰色背景
从中间带灰色背景的article
元素可以看出,这一行中的三个article
充满了容器元素section
,而且彼此之间亲密无间。
再强调一次吧,每一栏中的间距要依靠内部div
。这个例子中的水平间距是由内部div
的左、右外边距生成的,它们把这个div
压缩了一下,这才使内容远离了父元素article
(如果此时直接给article
元素应用水平内边距的话,一定会破坏布局)。而每一栏中的垂直间距是由父元素的内边距生成的。为什么要用父元素呢?原因前面也提到过,就是在父元素没有上、下边框的情况下,子元素的上、下外边距会折叠的。
到此为止,我们关于这个布局的讨论就告以段落了。相信读者对如何使用上下文选择符一定有了深刻的理解。等到第7章,我们还将以这个布局为基础,创造出不一样的设计。