`

《精彩绝伦的CSS》图书试读样章

CSS 
阅读更多


--------------------------------------------------------------------------------------------
内容简介:
    打造现代布局的专业技术,本书远非只是介绍基础知识,它不仅全面细致地讲解布局与效果,而且展望了HTML5和CSS3的未来。业内很少有人能像Eric A. Meyer一样详细阐明CSS,他在本书中深入分析了普遍适用的实用技术,讲解了如何选用正确的工具、如何通过jQuery使用CSS效果和CSS3技术。
本书主要内容如下:
       显示或隐藏元素
       通过XHTML为body或html元素设置背景
       超过15种布局技巧,包括清除浮动、两栏/三栏布局、伪造栏布局、“唯一布局”、Holy Grail、基于em的布局、流式网格、固定页脚等
       各种CSS效果,包括CSS弹出框、框冲切、圆角、CSS精灵、滑动门、流式漂白、参差浮动等
       应用CSS表样式,包括使用表头、主体、脚注、行标题、面向列的样式、表的映射和图形化等
       使用CSS3元素、多背景支持、RGBA,以及通过jQuery执行CSS3选取操作等
    本书适合具有一定的CSS和JavaScript使用经验的Web开发人员学习参考。
-------------------------------------------------------------------------------------------------
作者介绍:
    Eric A. Meyer 
国际公认的HTML、CSS、Web标准方面的专家,自1993年开始从事与Web设计与开发相关的工作。著有《Eric Meyer谈CSS(卷1)》和《Eric Meyer谈CSS(卷2)》。

-------------------------------------------------------------------------------------------------


目  录
第一部分  基本原理
第1章  工具  2
1.1  Firebug  2
1.2  Web Developer Toolbar  8
1.3  IE开发者工具栏  13
1.4  Dragonfly(Opera浏览器)  16
1.5  Web检查器(Safari浏览器)  20
1.6  XRAY  22
1.7  SelectORacle  23
1.8  诊断样式表  24
1.9  重启样式表  26
1.10  IE9.JS  29
第2章  选择器  31
2.1  伪类与伪元素  31
2.2  为目标元素添加样式  33
2.3  特殊性  34
2.4  重要性  35
2.5  省略简写属性值的关键词时会发生
  什么  36
2.6  选择性地覆盖简写属性  37
2.7  通用选择  39
2.8  ID还是类  40
2.9  ID与类共用  42
2.10  多类  42
2.11  简单的属性选择  43
2.12  类的属性选择  45
2.13  ID还是属性选择器  46
2.14  部分属性值选择  47
2.15  更多部分属性值选择  48
2.16  选择后代元素  50
2.17  模拟部分子选择  51
2.18  兄弟选择  52
2.19  生成内容  54
第二部分  核心技术
第3章  提示  58
3.1  验证  58
3.2  调整字体值的顺序  59
3.3  玩转行高  60
3.4  无单位的行高值  61
3.5  避免缺少样式的边框值  62
3.6  使用颜色控制边框外观  62
3.7  抑制元素的显示  64
3.8  抑制元素的可见性  65
3.9  将元素移出屏幕  66
3.10  图像替换  68
3.11  打印样式  70
3.12  开发打印样式  71
3.13  块级链接  72
3.14  外边距还是内边距  73
3.15  凸排列表  75
3.16  为列表添加标记  76
3.17  通过背景实现列表标记  77
3.18  生成列表标记  79
3.19  不可不知的容器  81
3.20  文档背景  84
3.21  服务器特定的CSS  85
第4章  布局  88
4.1  用轮廓代替边框  88
4.2  居中块状框  90
4.3  通过溢出遏制浮动  93
4.4  通过浮动遏制浮动  95
4.5  清除浮动  96
4.6  相邻清除  98
4.7  简单的两栏布局  99
4.8  简单的三栏布局  100
4.9  伪造栏布局  103
4.10  流式漂白布局  106
4.11  唯一布局  109
4.12  Holy Grail  113
4.13  流式网格  117
4.14  基于em的布局  121
4.15  文档流中的负外边距  124
4.16  在特定的上下文中使用定位  127
4.17  将元素推出包含块  128
4.18  固定的页头和页脚  131
第5章  效果  134
5.1  复杂的螺旋  134
5.2  CSS弹出框  138
5.3  CSS菜单  140
5.4  框冲切  142
5.5  CSS3预备圆角  145
5.6  CSS3圆角  148
5.7  CSS精灵  150
5.8  滑动门  152
5.9  裁切的滑动门  155
5.10  CSS视差  157
5.11  参差浮动  160
5.12  更好的参差浮动  163
5.13  图像的框  166
5.14  受限的图像  168
第三部分  前沿技术
第6章  表格  172
6.1  表头、主体和脚注  172
6.2  行标题  175
6.3  面向列的样式  176
6.4  表的映射  180
6.5  表的图形化  186
第7章  可预见的未来  194
7.1  为HTML 5应用样式  194
7.2  像HTML 5一样给类命名  196
7.3  媒体查询  197
7.4  为特定的子元素应用样式  201
7.5  为特定的列应用样式  205
7.6  RGB alpha颜色  207
7.7  HSL颜色和HSL alpha颜色  208
7.8  阴影样式  210
7.9  多背景  212
7.10  二维变换  216

----------------------------------------------------------------------------------------

前  言
CSS已经发展得非常成功了,甚至像HTML一样成功!尽管有时候它的确令人难以掌控。现在无论是在浏览器还是应用商店,甚至聊天客户端,CSS都无处不在并且没有任何消退的迹象。随着这门语言的应用愈加广泛,其能力也在不断增强。
本书涵盖了近100个使用CSS制作优秀网站的窍门、技术、工具以及一些技巧,其中每个部分都是相对独立的。你可以随便翻开一页就读,而不用担心会错过前面章节中的某些重要内容。本书假定你至少已经熟悉一点儿CSS和CSS的使用,这种假定的熟练程度可以描述为“进阶的初学者到中级的使用者”。所以,如果你一点儿也不了解CSS,或者知道的比那些撰写规范的人都多,那本书恐怕不适合你。如果你不是这两类人,本书还是有很多值得学习和享受的内容的。
在本书的第一部分,我们对一些常用的工具和基本技术进行了介绍,其中还包括一些不那么好理解的CSS选择器。第二部分展示了CSS可以实现的各种各样的效果,其中包括一些好玩的特效、对同一目标的不同实现方式以及布局等。第三部分介绍的是前沿技术,这些技术或许你现在的项目里还用不到,但是随着时间的推移,它们一定会在你的工作中变得越来越重要。
请访问本书的网站www.wiley.com/go/smashingcss下载代码示例 。
大约十年以前,你可能还以为CSS大限将至了。但是到了2010年,它却变得更加充满活力且比以往更加引人注目了。我希望你能享受这前后封皮之间的内容,就如同我写作此书时同样地享受。
---------------------------------------------------------------------------------------------------------
试读

第二章:选 择 器

我们能真切地感觉到,选择器是CSS的核心部分。如果没有它们的话,我们除了把属性嵌入到每个元素里,就没有其他办法能把样式应用在元素上了,那真是太糟糕了。通过选择器赋予的选择任何形式任何种类元素的能力,我们可以只用很少的几行CSS完成很大一部分样式设置工作。

本章我们将深入探讨如何巧妙地使用选择器,并且概述一下哪些类型的选择器被普遍支持且应用最为广泛。

2.1 伪类与伪元素

在CSS中有两种“伪”字头的选择器:伪类(pseudo-class)和伪元素(pseudo-element)。CSS2.1中的伪类有:

:link——未访问过的链接;

:visited——访问过的链接;

:hover——鼠标悬停的元素;

:focus——获取焦点的元素;

:active——激活的元素(例如一个被单击的链接元素);

:first-child——作为其他元素第一个子元素的元素;

:lang()——根据元素的lang属性确定的元素。

CSS2.1中的伪元素有:

::first-line

::first-letter

::before

::after

那么区别在哪儿呢?区别就在于这些伪选择器影响文档的方式不同。伪类的表现有点儿像给文档添加类,而伪元素的效果就好像有元素被插入到了文档中。

以::first-letter为例,假设你要把每个h1的第一个字母增大到其他字母的两倍半(如图2-1所示),很简单:

h1::first-letter {font-size: 250%;}

这就仿佛CSS和标记被修改成了这样:

h1 first-letter {font-size: 250%;}



<h1><first-letter>H</first-letter>owdy, y’all!</h1>



图2-1 放大h1的第一个字母

这真的是浏览器内部真实发生的情况吗?谁知道呢,反正结果确实像是发生了这种情况,因此才有了“伪元素”这个名字。

类似地,伪类的表现就像是它们使文档中的元素被添加了新的类。例如,想象一下若对于每一个作为其他元素第一个子元素的元素,浏览器给它们都附加了一个名为first-child的类,然后就可以像下面这样为它们应用样式了:

li.first-child {border-left: none;}

只需要简单地把点改成冒号就变成了li:first-child,就可以得到同样的最终效果,而不用费力把类添加到所有标记上。

有时还会看到伪元素使用双冒号的语法,这是在CSS2.1之后引入的。截至撰写本书之时,还没有哪个浏览器要求你必须在伪元素前面使用双冒号的,一个冒号就可以了。

另外提醒读者,CSS3增加了如下一些伪类,截至撰写本书之时,它们中的大部分还没有被广泛地支持:

:target

:root

:nth-child()

:nth-of-type()

:nth-last-of-type()

:first-of-type

:last-of-type

:only-of-type

:only-child

:last-child

:empty

:not()

:enabled

:disabled

:checked

2.2 为目标元素添加样式

当希望指向文档中的某个片段时,目标(target)会非常有用。什么,怎么实现?其实非常简单:

<a href="http://example.com/law.html#sec2-7">Section 2.7</a>

任何人单击这个链接(如果浏览器处理正确的话)将不止跳转到目标页,而且还会跳到页面中文档片段标识符(地址中的#sec2-7部分)出现的地方。这有时是通过锚点(anchor)实现的,但是只用ID来实现会更好一些。例如有如下两种场景:

<h3><a name="sec2-7">Exceptions</a></h3>

<h3 id="sec2-7">Exceptions</h3>

这两种情况下,当浏览器跳到了文档中的目标位置时,都不会有任何视觉提示告知你已经到达了目标位置,而使用:target伪类就可以给出视觉提示。例如,若想让作为某个文档片段标识符目标的h3拥有特定的提示效果(如图2-2所示),可以这样写:

h3:target {color: maroon;

    background: #FFA;}



图2-2 突出显示目标元素(另见彩插图2-2)

当然,你或许想把这个样式应用到任何目标元素上,而不管它是什么元素,那么只需要把h3换成一个通用选择器即可,就像这样:

*:target {color: maroon;

    background: #FFA;}

从技术上讲,这种情况下通用选择器也是可选的,可以把这个选择器简单地写成:target。

如果想让目标样式多一点Web 2.0的感觉,还可以设置一个渐隐背景的效果。你懂的,就是那种“你已经完成了某项操作,所以页面上的一块背景会从黄色变到白色,让你知道已经完成了该项操作”的效果。通过:target和一个动画GIF可以很容易地实现这种效果,只需要创建一个从黄色渐变到白色(如果白色是你网站的背景色的话)的动画并且把它当做背景图像。

*:target {background: url(/pix/yellow-fade.gif);}

2.3 特殊性

你很难快速地把特殊性(specificity)这个词读3遍,而若想彻底地掌握它甚至更难。但是,它却是理解CSS规则之间相互作用的关键。

特殊性是一个选择器“特殊程度”的数字表示,有3样东西经常被用来确定选择器的特殊性:

每个元素描述符贡献0,0,0,1;

每个类、伪类或者属性描述符贡献0,0,1,0;

每个ID描述符贡献0,1,0,0。

先不要抓狂,来看几个小例子。
div ul ul li 0,0,0,4 4个元素描述符
div.aside ul li 0,0,1,3 1个类描述符,3个元素描述符
a:hover 0,0,1,1 1个伪类描述符,1个元素描述符
div.navlinks a:hover 0,0,2,2 1个伪类描述符,1个类描述符,2个元素描述符
#title em 0,1,0,1 1个ID描述符,1个元素描述符
h1#title em 0,1,0,2 1个ID描述符,2个元素描述符
希望这些能够帮助你理解特殊性是如何计算的。那么,为什么是逗号呢?因为可以这么说,每个“级别”的特殊性的值都是相互独立的。因此,具有一个单独的类描述符的选择器会比由13个元素描述符组成的选择器拥有更高的特殊性。

.aside    /* 0,0,1,0 */

div table tbody tr td div ul li ol li ul li pre    /* 0,0,0,13 */

第一个选择器左数第三位的“1”胜过了第二个选择器同样位置的“0”,基于这样的事实,第二个选择器第四位的“13”(在这个非常有限的例子中)就毫无意义了。逗号可以使我们看得更清楚,否则选择器的特殊性可能被写成“10”和“13”,从而造成后者特殊性更高的假象(在CSS的早期还没有引入逗号分隔符时,这是经常出现的误解)。

还有另外一种常见的误解,就是特殊性的结构相近问题。例如,假设有如下两个选择器:

ul li {font-style: normal;}

html li {font-style: italic;}

它们当中哪个会赢呢?它们都有两个元素描述符,这意味着它们的特殊性都是0,0,0,2。其实,后写的会赢,与html元素相比ul元素在文档中的位置离li元素更近也不管用。特殊性只是单纯的数值,它不会以任何方式评估页面的结构。结果,列表元素将全部变成斜体,因为当特殊性相等时后声明的规则会胜出。

因为我说过有3样东西影响特殊性,所以你或许想知道特殊性标识符第一位的0是干嘛用的。其实,第一个0是用于行内样式(inline style)的,且仅用于行内样式。因此,如果有下面这样的样式和标记,则div的背景将会是蓝色。

div#header {background: purple;}  /* 0,1,0,0 */



<div id="header" style="background: blue;">  <!-- 1,0,0,0 -->

2.4 重要性

有一样东西是可以无视特殊性的,那就是!important。如果你是一名程序员的话,我现在就要打消你的错误想法——!important不代表 “不重要” 。

可以使用!important把任何单独的声明标记为重要。下面是一个简单的例子:

a:hover {color: red !important; text-decoration: none;}

在这个例子中color: red被标记为重要,但是text-decoration: none没有。任何你想标记为重要的声明都需要有自己的!important。

基本上,任何重要的声明都会覆盖非重要的声明。好了,就此打住吧。使用下面的代码,结果将会得到一个绿色的链接:

div#gohome a#home {color: red;}

div a {color: green !important;}



<div id="gohome"><a id="home" href="/">Home</a></div>

第一个规则非常高的特殊性(0,2,0,2)对于解决颜色冲突没有任何作用,因为!important可以胜过它。

当然,如果我们为第一条规则也添加一个重要标志,那么情况就不同了。

div#gohome a#home {color: red !important;}

div a {color: green !important;}

由于两个颜色声明都是重要的,所以会采用正常的层叠规则来解决冲突,换句话说,特殊性又起作用了,所以链接会变成红色。

这提醒我们使用!important时要非常小心,因为一旦开始用它覆盖其他规则,很快你就会发现必须再用另外的!important覆盖这条重要的规则,因此就必须再引入一个!important声明,最终会把所有的声明都变成重要的,也就意味着最终没有一个规则是重要的。

2.5 省略简写属性值的关键词时会发生什么

我们都知道CSS中有很多简写属性,其中background、border、font、margin和padding是几个最常用的,这是一次表达一堆信息的高效而简洁的方式。但是,当省略了属性值中的某些部分时会发生什么呢?考虑下面的代码:

strong {font: bold italic small-caps medium/1.2 Verdana, sans-serif;}

如图2-3所示,这会对strong元素应用1.2倍行高且字体为粗斜体、中等字号、小型大写字母(small-caps  medium-size)的Verdana(或者其他sans-serif字体族 的字体)样式。



图2-3 疯狂的strong

假设我们缩减一下这个属性值:

strong {font: medium Verdana, sans-serif;}

则结果是中等大小、正常粗细的Verdana字体(如果Verdana字体不可用的话就是其他的sans-serif字体),而粗体的效果消失了,如图2-4所示。



图2-4 因疏忽而无加粗效果

原因是当省略了部分简写属性值的时候,缺失的部分就会使用该属性的默认值。因此,当省略了字体粗细(font-weight)、字体样式(font-style)和字体异体(font-variant)时,实际相当于这样:

strong {font: normal normal normal small/normal Verdana, sans-serif;}

是的,即使行高line-height也有默认值,该默认值可以覆盖任何继承的行高值。

如果设置样式的时候不小心,就可能会出现类似的问题。考虑下面两条规则,第一条来自于全站的样式表,而第二条来自于某个页面的嵌入样式。

body {background: #FCC url(/i/pagebg.gif) 10px 25% no-repeat fixed;}

body {background: url(i/body-bg.gif);}

在这两条规则的作用下,这里讨论的页面会有一个新的从左上角开始的背景图像,且当页面滚动时会随着页面滚动。这是因为第二条规则实际上等价于:

body {background: transparent url(i/body-bg.gif) 0 0 repeat scroll;}

现在,如果这确实是想要的效果,那么你可以这么做,但它的目的似乎更像是要把图片换成另外的图片。其实在这种情况下,你只需要设置特定的属性,像这样:

body {background-image: url(i/body-bg.gif);}

总之,这是大部分简写属性的工作方式。不过,也有一些例外的,如margin、padding、border-style、border-width和border-color等,省略这些属性的值,结果就像是从已给出的值“复制”了一份。下面有几个功能相同的声明:

margin: 1em;    margin: 1em 1em 1em 1em;

padding: 10px 25px;    padding: 10px 25px 10px 25px;

border-color: red green blue;    border-color: red green blue green;

当然,这些值的顺序还是上右下左(Top-Right-Bottom-Left),可以简记为TRBL,这可以免除你“记不住”这一麻烦(TRouBLe)。

2.6 选择性地覆盖简写属性

虽然简写属性会用默认值覆盖未声明的部分,但这并不意味着我们需要避免这种情况。实际上,你可以用简写属性声明80%,然后在另一处通过覆盖实现另外20%。

假设你想实现一个具有3 px的点线边框,其中3条边是黑色,而第四条边是红色(如图2-5所示),可以每次都写一个边,但是那样要多敲很多次键盘。所以可以像下面这样声明:

border: 3px dotted black;

border-left-color: red;

这样,就只需要调整那一小部分跟其他部分不同的地方。你甚至可以用同样的规则实现一些更好的效果。

再举一个常见的选择性覆盖简写属性的例子。注意,标题元素可能除了字号以外大部分属性都相同。如果你对浏览器默认的字号很满意的话,就可以直接这么写了:



图2-5 把一侧的边变成红色(另见彩插图2-5)

h1, h2, h3, h4, h5, h6 {font-weight: normal;

font-style: italic;

font-family: Helvetica, sans-serif;

line-height: 1.5;}

另一方面,如果想设置自己的标题字号,如图2-6所示,则需要换个思路:

h1, h2, h3, h4, h5, h6 {font: italic 100%/1.5 Helvetica, sans-serif;}

h1 {font-size: 225%;}

h2 {font-size: 185%;}

h3 {font-size: 140%;}

/* …… */



图2-6 通过选择性覆盖快速设置标题字号

当使用这种选择性覆盖时,最好确保用来覆盖简写属性的属性出现在简写属性之后。只有通过这种方式,当选择器具有相同的特殊性时(这也是经常出现的情况),用来覆盖简写属性的属性才能胜过相应的简写属性。

2.7 通用选择

本节我将介绍一下选择器中星号(*)的使用,先别太兴奋,它并不是你想象中的万能牌。下面是一个简单的例子:

* {color: blue;}

这个星号称为通用选择器,该选择器的作用是选择文档中的全部元素并对其应用样式。

这看起来像是一个通配符,而且在某种情况下确实是,因为你可以用它选择一大堆元素而无需给它们命名。假设我想选择这个div中的全部元素:

<div>

<h1>Hey-ho!</h1>

<p>I’m a <em>paragraph</em>.</p>

<ol>

<li>Uno</li>

<li>Deux</li>

<li>Drei</li>

</ol>

</div>

就这么简单:

div * {border: 1px solid red;}

结果跟这样写的效果是一样的:

div h1, div p, div em, div ol, div li {border: 1px solid red;}

好吧,应该说是几乎一模一样。如图2-7所示,视觉效果是一样的,但是还有一个非常轻微的不同,那就是它们的特殊性。你可以看到,通用选择器的特殊性贡献为0,0,0,0,这意味着div *的特殊性为0,0,0,1,而div h1(还有这一组里的其他选择器)的特殊性为0,0,0,2。除了这个,结果是一样的。



图2-7 把div的所有后代加上红框(另见彩插图2-7)

你或许以为可以用h*来代替h1、h2、h3、h4、h5、h6,但是对不起,不行。就像前面展示过的,只能把它作为一个元素通配符,这就是它的全部功能了。

2.8 ID还是类

任何一个有抱负的网页设计师遇到的第一个大难题就是:我该用类(class)还是ID呢?

就像生活中的许多事情一样,这个问题有一个简单的答案,然而也有一个非常复杂的答案。简单的答案是:对于任何在页面中可能出现不止一次的“标签”使用类,对于任何只出现一次的使用ID。这里所谓的“标签”,指的是一个附加到元素上的描述性词汇。实际上,类和ID有99.44%的可能性被用在描述元素上。

使用ID值的两个经典例子是页头(header)和页脚(footer),前提是任何给定页面都只有一个页头和一个页脚。类值的应用就比较分散了,比如可以用more表示“详细信息”链接,用tabs表示一组导航选项卡,或者用odd表示奇数表格行。

至于那个更复杂的答案就不仅要权衡标签是否在页面中唯一了,还要考虑到ID和类对特殊性的影响。由于包含ID的选择器比那些只包含类的选择器具有更高的特殊性,因此你可能会无法覆盖某个特定规则。

这里有个简单的例子,假设你已经在全站样式表中写过如下规则:

#header {background: black;}

#header a {color: white;}

然后你又决定让联系信息页面不要那么严肃,所以想把页头设置成浅灰色,并让所有的导航链接有一个舒缓的暗绿色样式。由于该联系信息页面有几组不同的导航链接,所以你会这么写:

#header {background: #BBB;}

.navlinks a {color: #257000;}

很遗憾,如图2-8所示,因为#header a具有更高的特殊性,所以页头的导航链接仍然是白色。



图2-8 页头毫无吸引力的链接

对于这个问题,可以这样来解决:

#header a, .navlinks a {color: #257000;}

甚至这样:

#header .navlinks a, .navlinks a {color: #257000;}

这两种方式都可以,不过看起来有点儿笨拙,不是吗?(虽然不如往.navlinks a上砸个!important那么笨,但还是有点儿笨。)另外一个处理这种情况的方法是将包含ID的页头标签里面的id换成类,即:

<div class="header">

此处的class="header"原来是id="header"。这样就不用太担心ID弄出来的那些很难搞的特殊性冲突问题了。也就是说,在你的全站样式表中这么写:

.header {background: black;}

.header a {color: white;}

然后在联系信息页面的样式表中这么写:

.header {background: #BBB;}

.navlinks a {color: #257000;}

最终结果就是漂亮的绿色文字链接,如图2-9所示。



图2-9 页头引人注目的链接(另见彩插图2-9)

这就是全部需要做的工作了,所以,这是为大部分或者全部标签都应用类的一个好理由。

另外一个理由是,你没法确定什么时候标签会从一个变成多个。页头(header)就是个最好的例子,因为一个页面中可能有多个“页头”。如果觉得奇怪的话,想想新闻网站或者其他门户网站,每个部分和侧栏框都会有自己的“页头”,并且页脚也一样。因此一贯地使用类就很合理了。

现在,你或许会争辩说那些并不是一个页面上真正的页头和页脚,它们只是标题和其他附加信息或者诸如此类的内容。其实这是个语义问题,是没法明确解决的,比如你称为首行的,我可能叫它头部。关键是你用于网页的唯一标签有朝一日可能变得不再唯一。避免这种情况发生的最好办法就是一开始就全部使用类。

那么有没有什么用得着ID的地方呢?当然可以有。总会有一些情况下,你可以确定某个元素在页面中是唯一的,并且永远不会重复。还有一些情况下,你希望用ID给选择器赋予更高的特殊性,以便轻松地使它胜过其他选择器。并且ID对于脚本编程、链接目标和其他CSS之外的东西都至关重要,你只需要在书写CSS时小心一点儿就是了。

还有另外一种可以使用ID且不用担心特殊性问题的方法,我们在2.13节介绍。

2.9 ID与类共用

偶尔可能会有这样的情况,有一个唯一的元素并且它还是一大类元素中的一分子。例如,假设站点侧边栏中有一堆小面板,每个面板都有一个框并且具有特定的颜色和字体,但是每个面板都有独特的地方,比如每个都有不同的背景图等。

在这种情况下可以给元素同时应用类和ID,就像这样:

<div class="panel" id="weather">

<div class="panel" id="stocks">

<div class="panel" id="latest">

然后,在CSS里就可以按需处理了。

.panel {

    border: 1px solid silver;

    background: #EEE top left no-repeat;

    color: #333;

    font: x-small sans-serif;}

#weather {

    background-image: url(/pix/panel-weather.jpg);}

#stocks {

    background-image: url(/pix/panel-stocks.jpg);}

#latest {

    background-image: url(/pix/panel-latest.jpg);}

你甚至可以把其中两个组合为一个选择器,像这样:

.panel#weather {font-weight: bold;}

#latest.panel {color: #511;}

没错,它们的书写顺序无关紧要,不必跟它们在HTML中出现的顺序一致。

2.10 多类

元素的class属性有个经常被忽略的能力,就是你可以用任意多的词组成一个由空格分隔的列表,将其作为该属性的值。换句话说,就是你可以给元素应用多个类。

作为例子,我们继续使用之前的标记并把它改成不使用id属性的状态:

<div class="panel weather">

<div class="panel stocks">

<div class="panel latest">

然后只需要调整CSS使其能够应对用类代替ID的情况:

.panel {

    border: 1px solid silver;

    background: #EEE top left no-repeat;

    color: #333;

    font: x-small sans-serif;}

.weather {

    background-image: url(/pix/panel-weather.jpg);}

.stocks {

    background-image: url(/pix/panel-stocks.jpg);}

.latest {

    background-image: url(/pix/panel-latest.jpg);}



.panel.weather {font-weight: bold;}

.latest.panel {color: #511;}

类在HTML源代码中的书写顺序与在样式表中的书写顺序无关,即.panel.weather的效果跟.weather.panel的效果是一样的,并且无论这两个类在HTML源代码中的书写顺序如何,特殊性也都是一样的。它们在源代码中是否被其他类名分隔开也是无关紧要的,比如:

<div class="weather alert tornado watch panel">

此时通过.panel.weather和.weather.panel都可以选中该元素。

有个正在慢慢被忽略的注意事项 :IE6及早期版本不识别样式表中多个类的写法,当使用.panel.weather时,IE6只会识别成.weather。尽管在HTML中仍然可以使用多个类,并且可以在CSS中定位这些类,但是每次只能使用一个类。因此,.weather和.panel都可以在IE6下很好地匹配之前例子中的标记,只是IE6会假定.weather.panel给元素应用了一个包含panel这个词的类,这可能并不是你想要的结果。

2.11 简单的属性选择

属性选择器是CSS2中引入的并且在CSS3中得到了扩展,截至撰写本书之时已经得到所有主流浏览器的支持(IE6除外,如果这对你来说是个问题的话,参见1.10节)。

最基本的思路就是可以通过元素已有的属性选择元素,或者基于元素属性值的某个方面进行选择。因此,你可以选择所有确实是链接的a元素,像这样:

a[href]

该选择器会选择所有含有href属性的a元素,不会选择没有href属性的a元素,命名锚点(例如<a name="top">)就是最明显的例子。它基本上是a:link, a:visited的一个简化版。例如应用:

a[href] {color: green;}

则页面将会如图2-10所示。

至于href的属性值是什么一点都不重要,实际上甚至连属性值是否为合法的URI(Uniform Resource Identifier,统一资源标识符)或其他资源都无关紧要。选择<a href="#">和选择
<a href="http://w3.org/">的方式完全相同。



图2-10 通过属性选择器选择链接元素

现在,如果想选择指向某个特定地址的全部超链接该怎么做呢?若想筛选出一个特定的URI,只需要这么做(如图2-11所示):

a[href="http://w3.org/"] {font-style: italic;}



图2-11 通过属性选择器选择具有特定URL的链接元素

该选择器只会选择href属性值中包含http://w3.org/的链接元素,注意到我的措辞了吗?我没有说“指向W3C网站的超链接元素”,因为事实并非如此。这里面的原则是必须做到精确匹配,每个字母都要匹配。如果有这样一个链接<a href="http://www.w3.org/">,则该选择器不会选择这个链接,因为必须做到精确匹配才行。

或许这对于超链接来说用处不太大,但是它可以帮助筛选特定的图像(以便为其添加样式),比如公司的标志。如果你的CMS总是为页顶的标志生成这样的标记:

<img src="/img/2010/mainlogo.png" alt="ConHugeCo Inc." />

则总是可以用这样的方式选择该图像:

img[src="/img/2010/mainlogo.png"]

你不需要给它设置类或者ID或者其他什么东西,而只需要基于src的值给它设置样式。前提是,正如我所说,你应该确定它总是会保持那个特定的值,而不会变成其他值。(对于非精确匹配,请参见2.14节。)

有一点需要注意,按照CSS规范,“选择器中属性名和属性值是否区分大小写取决于文档语言”(参见www.w3.org/TR/CSS2/ selector.html#matching-attrs)。换句话说,有些标记语言可能会区分属性名的大小写,而另外一些语言则不会。XHTML就区分大小写,所以你最好假定属性名和属性值都是区分大小写的。

2.12 类的属性选择

如果读过前面一节,你可能会想:“嘿,我可以用属性选择器改造一下.class符号啊!”是的,确实可以。只不过并不是我之前展示过的某种方法。

通过属性选择器我们可以实现跟div.panel一样的效果:

div[class~="panel"]

看到波浪号(~)了吗?就在等号的前面,在这种情况下它绝对是个关键部分。它的存在意味着该属性选择器会选择“以空格分隔的类名列表中包含该词的元素”,这就是小小波浪号的巨大作用。

为了加深理解,我来展示一下没有波浪号的话会发生什么。去掉波浪号后的选择器为:

div[class="panel"]

这会选择任何class属性的值为panel且只能为panel的div元素,如果某个元素的class属性值为panel weather,则这个选择器无法匹配该元素,因为panel和panel weather不是精确匹配。而另一方面,div.panel则可以很好地匹配<div class="panel weather">。

通过使用波浪号可以获得与“点类”(dot-class)语法完全相同的效果,因此下面两个规则除了输入的字母不同之外,其他方面完全相同:

div[class~="panel"]

div.panel

这时候你或许会想,“嘿,真棒!我一直想知道如何才能选择一个又长又复杂的类呢。”嗯,但是记住,属性选择器并不只局限于我们上面使用过的这两个属性——类和id。你可以选择任何属性值为可以被空格分隔的一串单词的元素,而说到“单词”,我指的是“字符构成的字符串”。

下面是使用属性选择器的其他几个例子:
img[alt~="figure"] 任何alt属性文本中包含“figure”的图像元素
table[summary~="data"] 任何summary属性文本中包含“data”的表格元素
*[title~="2009"] 任何title属性文本中包含“2009”的元素


2.13 ID还是属性选择器

不仅可以把属性选择器当做类选择器的加长替代版,还可以用它代替ID选择器。下面两条规则会选择同样的元素:

p#lead-in {font-weight: bold;}

p[id="lead-in"] {font-weight: normal; font-style: italic;}

很好,不过先花点儿时间考虑一下这两条规则的视觉效果:如图2-12所示,lead-in段落会同时拥有加粗和斜体的效果。



图2-12 根据不同的特殊性合并样式

这是因为属性选择器的特殊性贡献为0,0,1,0,与类和伪类的贡献相同。因此第一条规则的特殊性为0,1,0,1,而第二条规则的特殊性为0,0,1,1。在字体粗细的斗争中,第一条规则因其较高的特殊性胜出了。

这是特殊性的一个有趣的小技巧,通过它可以引入崭新的创作模式。例如,你或许还记得之前在2.8节讨论过的ID会轻松地胜过类,并且你或许已经考虑用类来选择所有的标签了。如果用户群都在使用支持属性选择器的浏览器,那么你就又可以把ID和类混着用了,然后在需要通过ID引用元素时使用属性选择器即可。通过这种方式,就不用担心#ID选择器的特殊性会胜过你写的其他任何东西了。

2.14 部分属性值选择

当CSS2完成之后,下个版本的CSS制定工作就开始了,即我们称为CSS3,尽管已经不再是一个规范了(这个说来话长)。其中一个最受关注的领域就是选择器,而属性选择器也不例外。规范的制定者们挑选出了一系列子串匹配模式,它们全都非常有用。

最基本的一个是子串匹配器。要想看看它有多大用处的话,考虑一个之前的例子:

a[href="http://w3.org/"]

该选择器会选择全部指向这个精确URL的链接元素,这没有任何问题。然而,假设有很多个链接到W3C网站,而不只是主页的链接,并且你还想对它们应用同样的样式。解决这个问题的一个好办法就是只选择URL中的w3.org部分,如图2-13所示。下面是具体做法:

a[href*="w3.org"] {font-weight: bold;}



图2-13 选择所有URL中包含w3.org的链接元素

是的,只需要在等号前面加个星号就行了。注意这不是通用选择器,也不能把星号放到值的前面来创建UNIX或者grep式的通配符。你只能把它放到等号的前面,意思是“属性值中将包含该字符序列”。

一如既往,这个选择器也可以用在任何元素的任何属性上。回顾之前选择公司唯一标志图像的例子,你还可以这样写:

img[src*="mainlogo.png"]

它会选择任何指向mainlogo.png文件的图像(img)元素,或者是src属性值中包含mainlogo.png这些字符的图像元素。因此,它将同时选择:

<img src="/img/2010/mainlogo.png.gif" alt="ConHugeCo Inc." />

<img src="/img/2010/mainlogo.pngdir/big.png" alt="ConHugeCo Inc." />

然而,你或许不应该这样命名文件和目录。当然,这只是建议。

有许多创造性的方式可以使用这种特殊的能力,通过选择图像元素URL中对应的部分可以选择来自于特定目录中的图像。因此,根据链接元素的href属性值,你就可以对链接到你网站某个特定区域的链接应用样式了。

a[href*="/contact"] {color: maroon;}

a[href*="/news"] {font-weight: bold;}

请牢记,应该区分属性值的大小写,因为这样可以把事情变得简单。因而下面的3个例子中头两个可以匹配到,而第三个则不能。

img[alt*="Figure"] {border: 1px solid gray;}



<img src="fig1.gif" alt="Figure 1. The larch." />

<img src="fig2.gif" alt="Figure 2. Mayor Quimby, a political figure of some note." />

<img src="digg.gif" alt="Several men trying to figure out how to dig a hole." />

第三个图像之所以没有匹配是因为“figure”与“Figure”是不同的。当然,在这种情况下或许是个好事,因为(根据alt的文本)第三个图像并不是作为常规的插图(Figure)出现的,它只是恰好在alt属性值中含有“figure”这个词而已。这也没关系,但是要知道下面的情况也会被匹配:

<img src="lost.gif" alt="Lost again. Figures, don’t it?" />

是的,是一样的“Figure”,所以会匹配。

如果知道大小写只差一个字母,那就很容易突破这种限制了。因此,如果想确保选择全部包含“Figure”和“figure”的实例,那么可以让选择器变成这样:

img[alt*="igure"] {border: 1px solid gray;}

当然它也会匹配诸如“configure”、“disfigure”和“oliguresis”等(仅举几例)这样的实例。

然而,子串选择并不止于此。具体将在下一节详细解释。

2.15 更多部分属性值选择

尽管任意属性值的子串匹配已经很好了(见2.14节),但有时你可能想限制只查找属性值的开头或结尾部分。幸运的是,确实有几个办法可以实现。

如果想根据属性值的开始部分的子串进行选择,可以使用这种模式:

a[href^="http"]

由于有了脱字符(^),该规则会选取任何href属性值是以http开头的链接元素。用这种方式很容易选择全部的站外链接。假设全部站内链接都是相对于页面或者站点的,并且在文件系统里不使用http字符串,则你可以简单地这样写:

a[href^="http"] {font-weight: bold;}

或者更复杂一点儿,像这样:

a[href^="http"] {padding-right: 18px;

    background: url(/pix/external.png) 100% 50% no-repeat;}

结果如图2-14所示。



图2-14 为http开头的链接添加图标

要想根据属性值的结尾子串选择元素,可以使用这个模式:

a[href$=".pdf"]

由于有了美元符号($),该规则会选择href属性值是以.pdf结尾的链接元素。这是使PDF文件下载链接变得显眼一些的简单办法,如图2-15所示。例如:

a[href$=".pdf"] {padding-right: 18px;

    background: url(/pix/pdf.png) 100% 50% no-repeat;}



图2-15 PDF文档链接的PDF图标

这真是太棒了!下面还有其他一些使用属性选择器对链接应用样式的例子。
a[href^="https"] 安全服务器链接
a[href^="mailto"] 电子邮件联系链接
a[href^="aim"] AOL即时通信服务链接
a[href$=".doc"] 微软Word文档
a[href$=".xls"] 微软Excel文档
a[href$=".zip"] 压缩文档
一如既往,记住这里并不局限于超链接。如果回想一下2.14节里“Figure”的那个例子,你会很快意识到许多问题都可以用一个简单的脱字符解决:

img[alt^="Figure"] {border: 1px solid gray;}

现在我们选择的图像元素的alt文本是精确地以“Figure”开始的,并且不用担心“Figure”出现在alt文本的中间或者其他地方的情况,这些情况都会被跳过。

2.16 选择后代元素

基于元素在文档结构中的位置选择元素也很常见,这通常是使用后代选择器实现的,就像这样:

div#header a {color: #DEFACE;}

该规则会选择id为header的div的后代元素(包含在div中)中的全部锚点元素(a)。

大多数情况下,这确实是我们想要的效果:选择头部的链接元素而不用管它们在头部的位置,也不用考虑两个元素之间会不会有其他元素。

然而,有时候你或许想选择作为其他元素子元素的那些元素,而不是任意的后代元素。想象一下只选择作为有序列表(ol)元素子元素(而不是后代元素)的列表项(li),如图2-16所示。这样,如果有任何无序列表包含在该有序列表中,则它们的列表项不会被选中。我们需要的只是一个子选择符。

ol > li {list-style-type: upper-alpha;}



图2-16 只选择作为有序列表子元素的列表项

这个大于号限制了只能选择有序列表的子元素。如果把它去掉的话,该规则就会应用在作为有序列表后代的任何列表项上,包括嵌套的列表项(参见图2-17)。

是的,确实会发生这种情况,我没骗你。图2-17中展示的是含有有序列表标志的无序列表,发生这种情况只是因为我去掉了大于号。



图2-17 无序列表项被应用了编号样式

2.17 模拟部分子选择

如果不得不支持像IE6这种不支持子选择符的古董浏览器,并且也不想靠JavaScript添加对这些浏览器的支持(见1.10节),那你可以通过通用选择器模拟子选择。

假设我们希望为id为main的div中的全部div添加一个边框(如图2-18所示),使用子选择符的方式为:

div#main > div {border: 1px solid gray;}



图2-18 伪造子选择

好了,那么我们怎么模拟这个效果呢?这样:

div#main div {border: 1px solid gray;}

div#main * div {border: 0;}

第二条规则选择了id为main的div的所有后代的后代div元素。实际上,它撤销了第一条规则的效果。两条规则都应用到div#main的孙子div上,并且都设置了边框,因而它们是冲突的。但因为它们具有相同的特殊性,所以最后一个规则胜出。至于div#main中的div元素则只能被两条规则中的第一个选中,所以边框仍然还在。

有一点是需要牢记的,这个“伪造”子选择技术只能用于非继承的属性。对于可继承的属性,你可以创建一些意想不到的效果。举个例子,假设你写了如下规则:

ol li {font-weight: bold;}

ol * li {font-weight: normal;}

假设你希望加粗具有某个特定类名的有序列表下的无序列表的字体(如图2-19所示):

ol.urgent ul {font-weight: bold;}



图2-19 继承的样式被直接指定的样式覆盖了

加上这条规则后,这些无序列表中的列表项会怎样?不加粗!为什么?这是因为之前展示的ol * li规则会直接作用到这些列表项上,因此,font-weight: normal会覆盖它们从ol.urgent li规则继承来的加粗(bold)的值。

如果使用非继承的属性就不会发生这种情况了,比如background(背景)、border(边框)、display(显示)、margin(外边距)、padding(内边距)等。如果你还不清楚哪些属性是继承属性,可以看这里w3.org/TR/CSS2/propidx.html或者看CSS规范中关于属性的描述部分。

2.18 兄弟选择

除了能够依据父子关系和祖先后代关系选择元素之外,基于元素已有的兄弟元素(即它们共同拥有一个父元素)来进行选择也是可能的。在图2-20中可以看到,突出显示的即为兄弟元素。



图2-20 突出显示的兄弟元素

其实列表项就是很典型的兄弟元素,任何拥有同一个父元素的元素都是兄弟元素。图2-21中选择了跟在二级标题后的段落元素。



图2-21 选择紧跟在二级标题后的段落元素

CSS定义了一个选择符,它允许基于元素之前的兄弟元素来选择元素。例如,如果想移除任何紧跟在二级标题(h2)元素后的段落(p)元素的上外边距,则可以这样写:

h2 {margin-bottom: 0;}

h2 + p {margin-top: 0;}

兄弟选择很适合用于选择某些特定的元素组合并为其设置样式,比如为紧跟在div后面的表格或者标题元素之后的列表元素增加间距等。

还有一个非常类似的选择符,它允许选择后续的兄弟元素,但不包含直接相邻的兄弟元素。它使用一个波浪号作为选择符:

h1 ~ ul {list-style-type: lower-alpha;}

对下面的标记来说,这段代码会选择位于h1元素后面且与之共享父元素的ul元素,除第一个ul之外。

<body>

<ul>…</ul>

<h1>Planning</h1>

<p>This is an abstract.</p>

<ul>...</ul>

<ul>...</ul>

<h2>Introduction</h2>

<p>We have some thoughts here.</p>

<ul>...</ul>

</body>

由于这些元素共享父元素(body元素),因而它们都是兄弟元素。因为第一个列表元素没有跟随在一级标题h1后,所以它没有被h1 ~ ul选中,而其他列表元素都被选中了,虽然它们中间还有其他元素。

2.19 生成内容

CSS提供了一种可以生成内容并将其插入到文档中的方法,这使通常意义上的内容与表现的界限变模糊了。该方法是通过伪元素:before和:after以及它们的content属性实现的。

下面是个插入内容的例子(图2-22中亦有展示),在全部列表项的文本之前插入一个短字符串:

li:before {content: "Item: "; border-bottom: 1px solid gray;}



图2-22 在列表项前面加点儿内容

注意在content属性值中的空白,它是作为属性值字符串的一部分插入的。如果没有这个空白,也就没有右侧的内边距,元素就会和生成的内容贴得太近。(当然,我们完全可以给生成的内容设置右侧内边距,只是这里没这么做而已。)

要知道,只能插入文本而不能插入结构。如果试图把标记插入到content属性值中,则标记会被转换成纯文本。

li:before {content: "<em>Item:</em> "; border-bottom: 1px solid gray;}

如图2-23所示,悲剧了。



图2-23 标记被转换成了纯文本

另一方面,你也可以插入浏览器所支持的任何字符或图像字符(如图2-24所示),只需要知道它们的十六进制字符编码,并且在前面加一个反斜杠(也称作转义符)即可。

li:before {content: "\BB ";}



图2-24 通过转义编码插入字符

理论上讲,直接把Unicode字符写进CSS,把样式表全部改成Unicode编码也是可行的。然而,如果服务器配置为只能使用ASCII编码发送CSS,那可能会出现问题。如果你可以更改服务器配置的话,就不必转义十六进制字符,直接把字符写进样式表即可。不过,经过全面的测试,较老的浏览器可能无法恰当地处理Unicode字符。

:before和:after是伪元素,因为它们就好像在元素中插入了一个封闭的元素。这种伪元素可能放到元素内容的前面或着后面,这取决于使用了哪个伪元素。你可以像对待span那样对伪元素应用样式。

使用生成内容可以做很多有趣的事情,不过也要谨慎。设想如果CSS没有载入或者不被支持,页面会发生什么情况(例如在一些移动设备上)?如果使用生成内容插入一些对理解页面至关重要的内容,那么当没有生成内容时就会很麻烦。因此,强烈推荐仅将生成内容用于渐进增强 (progressive enhancement)的特性,以便当页面不支持这些特性时也可以正常展现内容。

向页面的打印副本中插入超链接URL就是个很好的渐进增强示例,如图2-25所示。为了实现这种效果,把下面的规则添加到打印媒体样式表中:

a[href]:after {content: " [" attr(href) "]"; font-size: smaller;}

这算是渐进增强,因为当浏览器不支持该特性时,打印页面会像往常一样只显示链接,而不显示生成的URL。当浏览器支持该特性时,打印页面就明显地被增强了。(关于该技术的更多内容,请见“Going To Print”,地址为http://alistapart.com/articles/goingtoprint。)

生成内容已经得到了广泛支持,但IE8之前的版本不支持生成内容。要让IE8之前的版本支持生成内容,可以使用第1章介绍的IE9.js。



图2-25 向打印样式表中插入链接URL

-------------------------------------------------------------------------------------------------------
http://www.ituring.com.cn/book/924
分享到:
评论

相关推荐

    精彩绝伦CSS2

    内容的内边距和外间距之间的间隙是留给边框的,CSS可以用边框属性来定义它的样 式、颜色和宽度等。 在Html中人们用表格来制作文本周围的边框,但通过CSS来设置边框将有更出色的效果,而且可以应用于所有的元素。 ...

    精彩绝伦CSS随书源代码

    精彩绝伦CSS书本的随书源代码,里面的例子还不错呢

    精彩绝伦的CSS

    精彩绝伦的css,适合中高级学者。ISBN 978-7-115-28479-2 精彩绝伦的CSS_13038327_北京市:人民邮电出版社_2012.07_(美)迈耶著_Pg226.pdf

    精彩绝伦的CSS.

    精彩绝伦的CSS 详细讲述css的内容 对入门的同学很有帮助 精彩绝伦的CSS 详细讲述css的内容 对入门的同学很有帮助

    精彩绝伦的CSS PDF版本下载.txt

    精彩绝伦的CSS PDF版本下载

    精彩绝伦的CSS. 最新 最全

    精彩绝伦的CSS. 最新 最全

    精彩绝伦的CSS(Smashing CSS: Professional Techniques for Modern Layout)

    精彩绝伦的CSS 英文原版pdf CSS专家Eric A. Meyer新作 全面解说CSS现代技巧和最佳实践 Smashing杂志专业策划 本书是国际知名CSS 大师写就的实用教程,分为3 部分。第一部分介绍了CSS 基础知识,对一些常用工具和...

    精彩绝伦的css

    介绍css布局、标签等,pdf版很清楚,值得一看

    高性能HTML5试读样章

    想让大规模高复杂度网站更快更易扩展?远不止H5/CSS3 这本彻头彻尾的实战书将教会你一切

    织梦地带CSS精彩教程

    [ 第 一 章 ] 什 么 是 CSS - 层 叠 样 式 表 [ 第 二 章] 简 单 的 CSS 层 叠 样 式 表 的 例 子 [ 第 三 章] 使 用 不 同 的 CSS 写 法 - CSS 进 阶 [ 第 四 章] 混 合 使 用 三 种 插 入 方 式 的 优 先 级 和 继...

    精通CSS 书籍的源代码

    精通CSS 书籍中的示例源代码 精通CSS 书籍中的示例源代码 精通CSS 书籍中的示例源代码

    DIV+CSS经典书籍

    DIV+CSS经典书籍 DIV+CSS经典书籍 DIV+CSS经典书籍

    CSS禅意花园中文试读版

    是试读的版本,网上好像没有中文完全版,买的比较贵,试读版里已经有很多好东西的~

    css3.0参考手册 css3.0参考手册

    css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css3.0参考手册css...

    CSS及其应用 书籍

    CSS及其应用 由我们老师整理的CSS文档

    精通CSS+DIV源码 第十章

    精通CSS+DIV源码 第十章 ……………………由于上传限制大小 所以只能一章章传了

    CSS3学习必备书籍《CSS3 实战》

    现如今,随着 Web2.0 技术的流行,之前的 CSS2 标准和相关技术似乎已经满足不了日益增长的开发需求:人们需要实现更加美观、用户体验更好的界面。CSS3,这个新一代的标准应运而生。为了满足现有的对于 Web UI 的开发...

Global site tag (gtag.js) - Google Analytics