作者:John Gallant , Holly Bergevin 翻译:w3cpro.cn
原文地址:http://www.communitymx.com/content/article.cfm?cid=1C603
翻译地址:http://www.w3cpro.cn/article/xhtmlcss/124.html
现在IE7已经推出一段时间并且渗透到用户当中,不用等太久我们就可以在页面上使用更高级的CSS。两个最有用的项目将是 Child子和Adjacent Sibling相邻兄弟选择符。现在已是时候使用它们制作网页,并且更深入研究它们。
注意,选择器包括现行的符号,“>”,“+”和空格(后代选择符),涉及到子选择器,相邻兄弟选择器,后代选择器,统称为选择符。
一个较好的方法
在我们研究选择符之前,弄清楚他们的不同和为什么它们是好东西的原因是个不错的主意。原因很简单,它减少网页的“class-itis”弊病。主要原因就是“class-itis”在目前网页中非常普遍,直到现在,我们拥有了为建立配合CSS选择器而存在而且支持完美的后代选择符,即两个选择器之间空格。
当使用后代选择符,右边的一个元素选择器是被选择的,不管左边的元素选择器标签有几个。举例,p a{color:red;},意思是段落里面的所有链接都是红色。这非常有用,也是一类相当广泛的选择组合。
代表性的class-itis的级数像下面一样。首先,你使用一个非常好的干净的html结构运用简单的CSS样式构建标题、段落等等。然后有人告诉你每个div块第一段里文本颜色需要红色。你不能仅改变目标段落的样式,因为那可能影响全部,所以你被迫命名一个特殊class应用在第一段。
于是数十次相同的要求在后面继续,结果就形成了class-itis现象。为什么说这样是糟糕有害的?因为这和font标签比起来没什么区别。当然,classes允许无穷的花样,但是紧随其后就是无穷的混乱,或可能更快胜于随后。
举个例子,假设你已经给所有第一段加上class属性,而且一切都好。现在你被告知,首两段需要样式,不仅是第一个。为使用正确class完成目的,你必须确信第二段的每个都有专用的class。最后,这样的习惯导致源代码里到处都是class,感觉像新旧两个样式在打斗冲突,让人头痛。
如果我们只针对CSS讲这样未必不好,实际上“运用下列样式到每个div块第一段和第二段里面。”这样的情况发生了,最新的CSS选择符允许我们耍点小聪明就可办到。
回顾复习下
让我们复习一些术语。W3C CSS2.1 规范解释了选择器(selectors)和选择(combinators):
“一个选择器是用选择符连接起来的一个或更多的选择器。选择符包括:空格,‘>’和‘+’。空格可能出现在一个选择符和简单的选择器之间。”一个简单的选择器可以是一种类型选择器或是通用选择器跟随零或者更多属性选择器,ID选择器或者伪类,在任何顺序。
第一个支持的选择符(也经常被称作选择器,这是唯一正确的部分)是子选择符。在简单的选择器之间指定“>”符号。一个简单的例子,#leftcol>p{color:blue;},意思是#leftcol下面所有子段落文本颜色是蓝色。
但是如果#leftcol有一个DIV,而且DIV还有一个段落,#left>p选择器不会使这个段落里的文本变成蓝色,因为子选择符,不像频繁使用的后代选择符,只选择直接的孩子,不是“>”符号的左边元素任何深度的嵌套后代。
另外一个新支持的选择符将是相邻选择符,使用"+"符号。子选择符可以指向另外一个元素的子部,相邻选择符可以指向跟随的元素,但与前面的元素独立。例子,h2+p {color:blue;},跟随h2元素后面段落的文本颜色为蓝色。
现在你明白选择符怎么工作,我们开始研究复杂联合元素,看看我们能不能不使用class达到目的。
使用选择符
我们从简单但充分复杂的html结构开始:
<div>First DIV
<p>Paragraph One -
<a href="#">link A</a>
<a href="#">link B</a>
</p>
<div>Second DIV
<p>Paragraph Two -
<a href="#">link C</a>
<a href="#">link D</a>
</p>
<p>Paragraph Three -
<a href="#">link E</a>
<a href="#">link F</a>
</p>
<p>Paragraph Four -
<a href="#">link G</a>
<a href="#">link H</a>
</p>
<div>Third DIV
<p>Paragraph Five -
<a href="#">link I</a>
<a href="#">link J</a>
</p>
<p>Paragraph Six -
<a href="#">link K</a>
<a href="#">link L</a>
</p>
<p>Paragraph Seven -
<a href="#">link M</a>
<a href="#">link N</a>
</p>
</div>
<p>Paragraph Eight -
<a href="#">link O</a>
<a href="#">link P</a>
</p>
</div>
<p>Paragraph Nine -
<a href="#">link Q</a>
<a href="#">link R</a>
</P>
</div>
图1 是html结构的文本对象模型树,图揭示了元素之间真实结构的联系。
在图1里兄弟元素分布在较低的支线上,它们的源头分布在图表从左到右顺序上。每组兄弟元素是它们所在支线会合顶点单一元素的子元素。如Paragraph One, Second DIV, and Paragraph Nine都是兄弟,而且都是First DIV的子元素。
图2使用清楚的样式显示它们怎么展示,First DIV的结构有Paragraph One, Second DIV, and Paragraph Nine组成。Second DIV有三个以上段落和拥有三个以上段落的Third DIV。所有段落的颜色是白色,每个包含两个链接元素。所有DIV黑色边框轻度褐色。
Image 2: DIVs are black-bordered and paragraphs are colored white for clarity.
这个结构可以进行许多选择符的试验。#p#分页标题#e#
试验
好了,让我们试着更改Second DIV的三四两个段落。如果我们只想使用后代选择符可以像这样div div p {color:red;};问题是上面的规则影响了Second DIV所有的段落,当然包括Third DIV的所有段落,因为Third div在DIV里面而段落在它里面。 还使用它?后代选择符没有一点选择性,让很多嵌套的元素都被选择当我们宁愿有给小的组选择。
的确,classes提供更好的选择性,但我们正试着避免class-itis。可是,不使用任何class仅使用相邻选择符比较困难。IE7 以前我们使用下面的方法:
div div p {color: red;}
div div div p {color: black;}
div div p.first {color: black;}
第一个规则应用了,然后带有另外DIV选择器的另外一个规则颠倒了Third DIV里的样式。随后阻止Paragraph Two的样式,我们没有选择,只有给段落指定一个class更换样式。真是痛苦!
通过子和兄选择符,我们可以很简单的实现,不需要class。
div>div>p+p {color: red;}
div>div>div p {color: black;}
Image 3: Our new combinators have selected only Paragraphs Three and Four.
让我们来分析下上面的代码,第一个规则的意思是:选择div的子部div的子部段落的相邻兄弟段落。
Second DIV是第一DIV的子部,Second DIV里面的两个段落即符合直接跟随另外一个段落的要求是Paragraph Two 和 Paragraph Three。Paragraph one没有被选中,因为在Second DIV里面没有兄弟段落在它前面。
这太棒了,但是还有一个问题。Third DIV同样是一个DIV的子部,同样有三个相邻段落的子部。我们不想Paragraph Six 和 Paragraph Seven被选中,所有必须制定一个规则,第二句的意思就是:选择div的子部div的子部div的后代段落。
对于我们测试的html,只有Third DIV里的段落适合描述的情况,所以对于目标段落它们用黑色文本代替红色文本。简洁明了,是不是?使用强大的后代、子、兄选择符,大部分class可以从我们的页面去除。我们也不是说大家一定要用到这些选择符,但是我们确信它们比单独使用后代选择符能够给你带来更多的适用性。
更多试验
现在我们试着选择Paragraph Eight里的link O 。你将会怎么做?花一点时间想下再看下面介绍的方法。
我们的方法
我们的第一个方法就是把Second DIV当做对象,然后使用兄弟选择符链接四个段落选择第四个段落,然后显示第四个段落的链接,最后写上段落的链接颜色代码。
div>div>p+p+p+p a {color: red;}
div>div>p+p+p+p a+a {color: blue;}
Image 4: A very narrowly defined element selection without using classes.
你们知道上面错在哪里了吗?考虑下Third DIV,它的位置正好和这四个段落有关。
那就对了,四个段落都是兄弟,但是Paragraph Eight不是Paragraph Four的直接相邻兄弟。Third DIV在它们之间必须作为兄弟考虑进去。我可以仅仅在第三和第四个"P"选择器之间粘贴一个DIV选择器,但是这里有另外一个简单方法实现我们的目
div>div>div+p a {color: red;}
div>div>div+p a+a {color: blue;}
上面的第一条语法指向Third DIV,然后选择它的直系兄弟段落(Paragraph Eight),最后选择段落里面的链接。“a”选择了段落里面所有的链接。接着第二条语句让跟随链接后面的所有链接为蓝色。所以link P的红色链接变成了蓝色,留下link O保持红色。好了我知道蓝色的链接是默认颜色,但我们学到了方法。
让我们最后阐明下窍门
考虑到一个元素包含很长的链接元素和其他(我们的例子没有提到)。如果你写个a{color:red;},所有的链接都是红色。现在写 a+a {color:red;},这个结构选择了另外一个直系跟随的链接。在我们的链接元素里每个链接都符合这样的描述,除了第一个链接。不要陷入到认为这个想法将选择互动链接。所有规则的意思是寻找和选择拥有直系并且在它前方有链接的任何链接。明显的除了第一个链接每个链接都是一致符合要求的。
第一个链接不跟随任何级数的链接,所以a+a{color:red;}没有被选择。知道这个事实,想象下在这个结构里我们添加另外兄弟选择符和“a”选择器每次会发现什么情况。a+a+a{color:red;}排除最初的两个链接,a+a+a+a{color:red}排除最初三个链接,等等。
所以如果你曾经看过,或你自己使用这个选择器窍门,仅仅只要记住这个基本规则:参加的兄弟选择器数目等于序列里第一个被选择的元素的位置。如果这里有8个"a"选择器通过七个兄弟选择符联合,第八个链接和级数里剩余的所有链接将被选择。因而,你可能把相同类型的一系列元素划分为两组,或是为后面的一组使用新样式或是为全组更换样式,然后再为后面的一组更换样式,你自己选择。
浏览器问题
IE7非常不幸的认为HTML注释也是真实的DOM元素,所以如果你在错误的地方使用注释,IE7将会把它当作兄弟计算在内,而你设定的选择器将不会工作。使用兄弟选择符时只要了解这个问题注意让注释出现在不会惹麻烦的地方。
另外一个知道的兄弟选择符问题,除了opera 9外的所有浏览器,当额外元素是经script增加的,它们不会解释基于样式表的兄弟选择符。所以如果你用script在元素中建立一个新的段落,只有Opera 9才会认识到从而改变样式。其他当前浏览器只会忽略动态结构,在新的元素添加进来前保持原来样式。
额外介绍下:first-child伪类
IE7新支持:first-child伪类。这个选择器的语法和用法和 :hover伪类相似,:first-child选择元素里出现的第一个子部,用法像:hover一样,比如链接会是a:first-child。
我们认识到使用:first-child比仅使用兄弟选择符来的简单。但在怎样获得赞扬或是用:first-child伪类选择器替换它之前,我们希望大家同样认识到兄弟选择符是怎么独立运用的。
比较下面的代码,使用:first-child简单许多。
使用 :first-child之前
div>div>div+p a {color: red;}
div>div>div+p a+a {color: blue;}
使用 :first-child...
div>div>div+p a:first-child {color: red;}
:first-child确实让工作简单许多!不需要另外规则改变样式,只要记住当使用:first-child,它只作用于第一个子部first child。没有其他兄弟元素被选择,所以我们还需要兄弟选择符的才干。
我们可不可以使用兄弟和子选择符联合:first-child?当然可以,子选择符看起来没有问题。可是,兄弟选择符不能直接跟在:first-child前面,因为很明显第一个子部不可能有上面的兄弟。
IE的问题
IE7似乎有一个问题,当兄弟选择符比:first-child在选择器中来的晚,IE7顺从兄弟选择符。这个情况也在其他浏览器有,但IE7显然不能处理相关的复杂性。这看来不够完美,不过至少IE7支持简单适度的联合结构,或许现在就可。
所以脑袋里记住,作为兄弟选择符,IE7将会考虑第一个链接前面的html注释为元素节点,而且IE7会选择注释代替,甚至你使用a:first-child都没用。IE7不关心:first-child伪类前面的"a",它仍然坚持选择注释(注释和第一个链接在同一个容器而且在链接前面)。所以当你使用注释和高级CSS选择器要清楚了解真相。
结论
我们希望这篇文章没有给你们带来困惑,当支持更多选择符时了解更多可以用到的可能性样式。这在IE7大规模推广前还没有用处,现在你可以做好准备,至少关注已经支持的选择符。