目录
CSS中,模式匹配规则规定文档树中的元素应该适用哪些样式规则。这些模式,称为选择子,可以是简单的元素名或者是复杂的上下文相关的模式。如果模式中的所有条件对某一个元素都为真,该选择子就匹配那个元素。
选择子中的文档语言元素名的大小写敏感性取决于文档语言的大小写敏感性。例如,在HTML中,元素名是大小写无关的,而在XML中,是大小写相关的。
下面的表格概括了CSS2选择子的语法:
模式 | 含义 | 定义在 |
---|---|---|
* | 匹配任意元素。 | 全局选择子 |
E | 匹配任意E元素(即类型为E的元素)。 | 类型选择子 |
E F | 匹配E元素后代的任意F元素。 | 派生选择子 |
E > F | 匹配E元素子元素的任意F元素。 | 子选择子 |
E:first-child | 当元素E是其父元素的第一个子元素时,匹配E元素。 | :first-child伪类 |
E:link E:visited | 当元素E是一个超连接的链时,如果目标还未被访问(:link)或已经访问(:visited)时,匹配元素E。 | 连接伪类 |
E:active E:hover E:focus | 在特定的用户行为时,匹配E。 | 动态伪类 |
E:lang(c) | 匹配E类型的元素,如果它以(人类)语言c写成(文档语言规定如何确定语言)。 | :lang()伪类 |
E + F | 匹配任意F元素,如果紧接在前的是E元素。 | 相邻选择子 |
E[foo] | 匹配任意E元素,如果它设置了"foo"属性(不管值是什么)。 | 属性选择子 |
E[foo="warning"] | 匹配任意E元素,如果它设置了"foo"属性,并且属性值为"warning"。 | 属性选择子 |
E[foo~="warning"] | 匹配任意E元素,如果它的"foo"属性值是一个以空格分割的列表,且其中之一为"warning"。 | 属性选择子 |
E[lang|="en"] | 匹配任意E元素,它的"lang"属性值是一个以连字号分割的列表,并且以"en"开头(从左到右算)。 | 属性选择子 |
DIV.warning | 仅对HTML适用。和DIV[class~="warning"]。 | 类选择子 |
E#myid | 匹配任何其ID为"myid"的E元素。 | ID选择子 |
一个简单选择子或者是一个类型选择子,或者是一个全局选择子,紧跟在后的是零个或多个属性选择子,ID选择子或伪类,次序任意。如果它的所有内容都匹配,则简单选择子匹配。
一个选择子是一个或多个简单选择子以组合符构成的链。组合符包括:空白,">"和"+"。空白可以出现在一个组合符和简单选择子之间。
文档树中匹配一个选择子的元素称为那个选择子的主题。包含一个简单选择子的选择子,匹配任意符合它要求的元素。将简单选择子和组合符结合成链就增加了额外的匹配条件,因此选择子的主题总是那些符合最右端的简单选择子的元素的子集。
在一个链中的最后一个简单选择子之后,可以加一个伪元素,这时它的样式信息应用到每一个主题的组成部分。
如果几个选择的声明类似,可以将它们分组为一个以逗号分割的列表。
本例中,我们将三个相同的声明归并为一个。因此,
H1 { font-family: sans-serif } H2 { font-family: sans-serif } H3 { font-family: sans-serif }
就等同于:
H1, H2, H3 { font-family: sans-serif }
全局选择子,写做"*",匹配任意元素类型名。它匹配在文档树中的任意一个元素。
如果全局选择子不是一个简单选择子的唯一内容,"*"可以省略。例如:
*[LANG=fr]
和[LANG=fr]
是一样的。
*.warning
和.warning
是一样的。
*#myid
和#myid
是一样的。
类型选择子匹配文档语言元素类型名。一个类型选择子匹配文档树中该元素类型的每一个实例。
如下的规则匹配文档树中所有的H1元素:
H1 { font-family: sans-serif }
有时,作者可能希望选择子在一个元素是文档树中另外一个元素的后代时,匹配那个元素(例如,“匹配那些包含在一个H1元素内的EM元素”)。派生选择就描述了模式中这样的关系。派生选择子有两个或多个选择子组成,并以空白相分割。派生选择子的形式为"A B
",它匹配一个元素B
,当元素B
是其前辈元素A
的任意后代时。
例如,考虑如下规则:
H1 { color: red } EM { color: red }
尽管这些规则的用意是通过改变文本的颜色来对文本进行强调,但是在下面的情况中就会失去强化效果:
<H1>本标题<EM>非常</EM>重要</H1>
我们这样来改进这一情况:我们对前述的规则补充一个规则,这一规则将出现在H1之内任何位置的EM元素的文本颜色设置为蓝色:
H1 { color: red } EM { color: red } H1 EM { color: blue }
第三个规则将匹配如下语句中的EM元素:
<H1>本<SPAN class="myclass">标题<EM>非常</EM>重要</SPAN></H1>
下面的选择子:
DIV * P
匹配一个P元素,如果该P元素是DIV元素的孙元素或更后的元素。请注意"*"两边的空白。
下面规则中的选择子结合了派生选择子和属性选择子,它匹配任何元素,如果(1)该元素设置了"href"属性;且(2)包含在一个P元素内,而P元素又包含在一个DIV元素内:
DIV P *[href]
子选择子匹配一个元素,当该元素是另外一个元素的子元素时。子选择子有两个或多个选择子构成,并以">"分割。
下面的规则集设置所有是BODY元素子元素的P元素的样式:
BODY > P { line-height: 1.3 }
下面的例子结合了派生选择子和子选择子:
DIV OL>LI P
它匹配一个LI元素的后代P元素;而LI必须是OL元素的子元素;而OL元素必须是DIV元素的后代。请注意,在">"组合符两端可选的空白已经被省略。
关于选择一个元素的第一个子元素的问题,请参见以下的:first-child伪类一节。
相邻同胞选择子的语法为:E1 + E2,其中E2是选择子的主题。该选择子匹配的条件是:如果E1和E2在文档树中父元素相同,且E1紧接在E2之前,则选择子匹配元素E2。
在某些情景中,相邻元素产生的格式化对象,它们的呈现是自动处理的(例如,相邻控制框之间的垂直边距的重合)。"+"选择子允许作者对相邻元素指定附加的样式。
因此,下面的规则指出,当一个P元素紧跟在一个MATH元素之后时,它不应该缩进:
MATH + P { text-indent: 0 }
下面的一个例子,缩小了紧跟在H1之后的H2元素的垂直距离:
H1 + H2 { margin-top: -5mm }
下面的规则同上一个类似,不过它加入了属性选择子。因此只有当H1具有class="opener"类时,才有特别的格式化:
H1.opener + H2 { margin-top: -5mm }
CSS2允许作者指定规则来匹配源文档中定义的属性。
属性选择子有四种匹配方式:
[att]
[att=val]
[att~=val]
[att|=val]
属性值必须是标识符或字符串。选择子中属性名和值的大小写敏感性取决于文档语言的敏感性。
例如,如下的属性选择子匹配那些指定了"title"属性的H1元素,而不论其值为什么:
H1[title] { color: blue; }
下面这个例子,选择子匹配所有指定"class"属性为"example"的SPAN元素:
SPAN[class=example] { color: blue; }
多重属性选择子可以用来引用一个元素的几个属性,或几次同一属性的出现。
这里,选择子匹配那些SPAN元素,其"hello"属性设置为"Cleveland"而"goodbye"属性设置为"Columbus":
SPAN[hello="Cleveland"][goodbye="Columbus"] { color: blue; }
下面的选择子显示了"="和"~="的区别。例如,第一个选择子匹配"rel"属性的"copyright copyleft copyeditor"值。而第二个选择子只匹配"href"属性值为"http://www.w3.org/"。
A[rel~="copyright"] A[href="http://www.w3.org/"]
下面的规则将所有"lang"属性设置为"fr"(即语种为法语)的元素的显示属性关闭。
*[LANG=fr] { display : none }
下面的规则将匹配包含以"en"开头的"lang"属性值的所有元素,包括"en","en-US"和"en-cockney":
*[LANG|="en"] { color : red }
类似地,下面的语音样式表规则允许一段文字根据不同的角色以不同的声音读出:
DIALOGUE[character=romeo] { voice-family: "Lawrence Olivier", charles, male } DIALOGUE[character=juliet] { voice-family: "Vivien Leigh", victoria, female }
匹配与文档树中的属性值紧密相关。除了HTML语言,其它文档语言的缺省属性可以定义在DTD中或别的地方。样式表的设计应该保证即使在文档树中没有包含缺省值,它们也可以正常工作。
假定我们考虑一个元素ELEMENT,它带有一个"notation"属性,其缺省值为"decimal"。则DTD表示可以是:
<!ATTLIST EXAMPLE notation (decimal,octal) "decimal">
如果样式表包含如下规则:
EXAMPLE[notation=decimal] { /*... default property settings ...*/ } EXAMPLE[notation=octal] { /*... other settings...*/ }
那么为了考虑属性是缺省地设置而不是显式地设置的情况,可以加入下面的规则:
EXAMPLE { /*... default property settings ...*/ }
由于这一选择子与属性选择子相比,不那么精确,它只可以用在缺省的情况下。注意,其它属性和缺省属性的样式不同,它们必须被显式地包含。
在HTML样式表中,当匹配"class"属性时,作者可以使用点(.)符号来作为"~="符号的替代。因此,HTML中"DIV.value"和"DIV[class~=value]"意思是一样的。属性值必须紧跟在"."之后。
例如,我们可以为所有class~="pastoral"的元素指定样式信息如下:
*.pastoral { color: green } /* all elements with class~=pastoral */或者:
.pastoral { color: green } /* all elements with class~=pastoral */
下面的规则只对class~="pastoral"的H1元素指定样式:
H1.pastoral { color: green } /* H1 elements with class~=pastoral */
在这些规则作用下,下面文字中的第一个H1元素不是绿色文字,而第二个是绿色文字:
<H1>Not green</H1> <H1 class="pastoral">Very green</H1>
要匹配"class"值的一部分集合,每一个值都必须以"."分割,次序任意。
例如,下面的规则匹配任意P元素,如果它的"class"属性被指定为一个空格分割的列表,并且其中包含"pastoral"和"marine":
P.pastoral.marine { color: green }
该规则匹配class="pastoral blue aqua marine"而不匹配class="pastoral blue"。
注意!CSS给予"class"属性很强的能力,基于没有呈现内容的元素(如HTML中的DIV和SPAN),用户几乎可以设计自己的“文档语言”,并通过"class"属性来指定样式信息。作者应该避免这一尝试。这是因为文档语言的结构化元素通常都有公认和认可的含义,而作者自定义的类却不是如此。
文档语言可以包含声明为ID类型的属性。ID类型属性的特殊之处在于,没有两个属性可以有相同的值;不管文档语言是什么,ID属性可以用来单一地指定它的元素。在HTML中,ID属性都被命名为"id";XML应用可能采取不同的方法命名ID属性,不过也有同样的限制。
文档语言中的ID属性允许作者为文档树中元素的一个实例指定一个标识符。CSS ID选择子基于元素的标识符来匹配一个元素。CSS ID选择子包含一个"#",紧跟在后的是ID值。
下面的ID选择子匹配ID属性值为"chapter1"的H1元素:
H1#chapter1 { text-align: center }
在下面的例子中,样式规则匹配ID值为"z98y"的元素。因此,规则匹配P元素:
<HEAD> <TITLE>匹配P元素</TITLE> <STYLE type="text/css"> *#z98y { letter-spacing: 0.3em } </STYLE> </HEAD> <BODY> <P id=z98y>宽文本</P> </BODY>
下一个例子中,样式规则只匹配ID值为"z98y"的H1元素,而不匹配例子中的P元素:
<HEAD> <TITLE>只匹配H1</TITLE> <STYLE type="text/css"> H1#z98y { letter-spacing: 0.5em } </STYLE> </HEAD> <BODY> <P id=z98y>宽文本</P> </BODY>
ID选择子比属性选择子具有更高的优先级。例如,在HTML中,从层叠的角度说,选择子#p123比[ID=p123]更明确。
注意!在XML 1.0[XML10],关于哪个属性包含了元素的ID的信息,存放在DTD中。解析XML时,用户端不总是阅读DTD,因此可能不知道元素的ID是什么。如果样式表的设计者知道或怀疑这里有问题,他应该改为使用一般的属性选择子:[name=p371]
来代替#p371
。然而,一般属性选择子的层叠次序和ID选择子不同。可能需要为声明加入一个"!important"优先权:[name=p371]{color: red ! important}
。当然,XML 1.0文档中的元素如果没有DTD,也就根本没有ID。
CSS2中,样式和元素的连接一般是基于元素在文档树中的位置。这一简化的模型对于大部分情况是足够的。不过由于文档树结构的限制,一些常用的印刷效果可能无法达到。例如,在HTML 4.0(参见[HTML40])中,没有元素可以来引用一个段落的第一行,因此也没有一个简单的CSS选择子可以引用它。
CSS引入了伪元素和伪类的概念,允许对文档树之外的信息进行格式化。
无论是伪元素或伪类,它们都不出现在源文档或文档树中。
伪类可以在选择子中的任何位置出现,而伪元素只可以出现在选择子的主题之后。
伪元素和伪类的名称是与大小写相关的。
某些伪类是相互排斥的,而其它一些可以同时应用到同一元素上。如果出现规则冲突,常规的层叠次序决定了最后结果。
与CSS一致的HTML用户端可能忽略所有带有:first-line或:first-letter的规则,或者,它们只支持这些伪元素属性的一个子集。
:first-child伪类匹配一个是另外一个元素的第一个子元素的元素。
下例中,选择子匹配任何一个是DIV元素的第一个子元素的P元素。该规则取消了DIV中第一个段落的缩进:
DIV > P:first-child { text-indent: 0 }这一选择子将匹配下面语句中在DIV内的P元素:
<P>在注释之前的最后一个P元素。 <DIV class="note"> <P> 在注释之中的第一个P元素。 </DIV>但是不匹配下面语句中的第二个P元素:
<P> 在注释之前的最后一个P元素。 <DIV class="note"> <H2>注释</H2> <P> 在注释之中的第一个P元素。 </DIV>
下面的规则匹配的条件是:如果P元素是某个元素的第一个子元素,且EM元素是它的后代,那么将EM元素的字体重量设置为'bold':
P:first-child EM { font-weight : bold }
注意,由于匿名控制框不是文档树的一部分,在计算第一个子元素时,它们不包含在内。
例如,下面的EM元素:
<P>abc <EM>default</EM>是P元素的第一个子元素。
下面两个选择子是一样的:
* > A:first-child /* A是任意元素的第一个子元素 */ A:first-child /* 同上 */
用户端显示未访问的连接和已访问的连接时,总有一些不同。CSS提供了伪类':link'和':visited'来加以区分:
注意!经过一段特定的时间后,用户端可以选择将已经访问的连接恢复到(未访问的)':link'状态。
这两个状态是互相排斥的。
文档语言决定哪些元素是超连接的源链。例如,在HTML 4.0中,连接伪类适用于带有"href"属性的A元素。因此,下面的两个CSS2声明效果一样:
A:link { color: red } :link { color: red }
如果下面的连接:
<A class="external" href="http://out.side/">external link</A>已经被访问,规则:
A.external:visited { color: blue }将使它成为蓝色。
交互的用户端有时根据用户的动作改变渲染效果。CSS为通用的情况提供三个伪类:
这些伪类互不排斥。一个元素同时可以匹配其中的若干个。
CSS并没有规定哪些元素可以由上述的状态,或者如何进入和离开这些状态。脚本可以改变元素是否相应用户事件。不同的设备和用户端对于指向和激活元素的表现方法可能有所不同。
用户端不必因为伪类的变换而重新排列当前显示的文档。例如,一个样式表可以指定一个:active连接的'font-size'要比一个未激活的连接大。不过由于这可能会在读者选择该连接时,改变字母的位置,用户端可以忽略相应的样式规则。
A:link { color: red } /* unvisited links */ A:visited { color: blue } /* visited links */ A:hover { color: yellow } /* user hovers */ A:active { color: lime } /* active links */
注意,A:hover必须放置在A:link和A:visited规则之后,否则层叠规则将隐藏A:hover的'color'属性。同样的,由于A:active放置在A:hover之后,激活的颜色(lime)在用户既激活又指向A元素时应用。
一个结合动态伪类的例子:
A:focus { background: yellow } A:focus:hover { background: white }
第二个选择子匹配在伪类:focus和伪类:hover中的A元素。
要了解焦点外廓呈现的信息,请参见动态焦点外廓一节。
注意!在CSS1中,':active'伪类和':link'、':visited'是互相排斥的。现在已经不是这样了。一个元素可以既是':visited'又是':active'(或既是':link'又是':active')。具体适用哪一个属性由一般的层叠规则决定。
如果文档语言规定了一个元素的自然语言是如何定义的,就可能基于元素的语言,写出CSS的选择子来匹配它。例如,在HTML[HTML40]中,语言是由"lang"属性、META元素、可能还有从协议得到的信息(如HTTP头)的组合决定的。XML使用一个XML:LANG属性。可能还有其它确定文档语言的方法。
伪类':lang(C)'匹配以语言C表示的元素。这里C是一个语言代码,定义在HTML 4.0[HTML40]以及RFC 1766 [RFC1766]中。它的匹配方式和'|='操作符一样。
下面这些规则为以法语或德语写成的HTML文档设置引号:
HTML:lang(fr) { quotes: '?' ' ? } HTML:lang(de) { quotes: '? '? '\2039' '\203A' } :lang(fr) > Q { quotes: '?' ' ? } :lang(de) > Q { quotes: '? '? '\2039' '\203A' }
第二对规则实际上是根据Q元素的父元素的语言,来设置Q元素的'quotes'属性。这是因为引号的选择通常是基于引语周围元素的语言,而不是引语本身:下面这个法语片段“à l'improviste”包含在中文文本中,因此使用中文的引号。
:first-line伪元素对一个段落的第一个格式化的行应用特殊的样式。例如:
P:first-line { text-transform: uppercase }
上面的这个规则意味着“将每一段的第一行的字母改为大写”。不过,选择子"P:first-line"并不匹配任何实际的HTML元素。它匹配由与CSS一致的用户端在每一段开始插入的一个伪元素。
注意,第一行的长度取决于很多因素,如页面的宽度,字体尺寸等等。因此,如下的一个很普通的HTML段落:
<P>This is a somewhat long HTML paragraph that will be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.</P>可能的分行如下:
THIS IS A SOMEWHAT LONG HTML PARAGRAPH THAT will be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.用户端可能加以“重写”以包含:first-line的虚构标记序列。这一虚构标记序列显示了属性是如何继承的。
<P><P:first-line> This is a somewhat long HTML paragraph that will </P:first-line> be broken into several lines. The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.</P>
如果一个伪元素截断了一个实际的元素,则需要的效果通常可以通过一个虚构标记序列来达到。改序列关闭并重新打开改这一被截断的元素。因此,如果我们在上面的例子中加入一个SPAN元素:
<P><SPAN class="test"> This is a somewhat long HTML paragraph that will be broken into several lines.</SPAN> The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.</P>用户端可能在为:first-line插入虚构标记序列时,为SPAN加入开始和结束标记:
<P><P:first-line><SPAN class="test"> This is a somewhat long HTML paragraph that will </SPAN></P:first-line><SPAN class="test"> be broken into several lines.</SPAN> The first line will be identified by a fictional tag sequence. The other lines will be treated as ordinary lines in the paragraph.</P>
:first-line伪元素只可以和块类元素连用。
:first-line伪元素和行内元素类似,但是有一些特定的限制。只有下列属性可以应用在:first-line伪元素:字体属性,颜色属性,背景属性,'word-spacing','letter-spacing','text-decoration',,'vertical-align','text-transform','line-height','text-shadow'以及'clear'。
:first-letter伪元素可以用于“词首大写”以及“大写字母下沉”,这些都是常用的印刷效果。这一类的首字母和一个行内元素类似,如果它的'float'属性是'none',否则它和一个浮动元素类似。
这些是可以应用在:first-letter伪元素上的属性:字体属性,颜色属性,背景属性,'text-decoration','vertical-align'(仅当'float'为'none'时),'text-transform','line-height',边距属性,边白属性,边框属性,'float','text-shadow'以及'clear'。
如下的CSS2规则将使首字母下沉扩展为两行:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"> <HTML> <HEAD> <TITLE>Drop cap initial letter</TITLE> <STYLE type="text/css"> P { font-size: 12pt; line-height: 12pt } P:first-letter { font-size: 200%; font-style: italic; font-weight: bold; float: left } SPAN { text-transform: uppercase } </STYLE> </HEAD> <BODY> <P><SPAN>The first</SPAN> few words of an article in The Economist.</P> </BODY> </HTML>
这一例子的格式化效果可能为:
虚构标记序列为:
<P> <SPAN> <P:first-letter> T </P:first-letter>he first </SPAN> few words of an article in the Economist. </P>
注意,:first-letter伪元素标记与内容(既第一个字符)毗邻,而:first-line伪元素的开始标记插入在伪元素所连的元素的开始标记之后。
为了得到常规的字母下沉格式,用户要对字体尺寸进行近似,例如对其基线。同样的,格式化时,也要考虑字型外廓。
标点符号(即定义为Unicode [UNICODE]中"open" (Ps), "close" (Pe)和"other" (Po)标点符号类中的字符),如果出现在首字母前,也要包含在内:
:first-letter伪元素只匹配块类元素的一部分。
某些语言对于如何处理特定的字母组合可能有特别的规则。例如,在德语中,如果字母组合"ij"出现在一个单词的开头,这两个字母都被认为是在:first-letter伪元素之内。
下面的例子显示了互相重叠的伪元素如何相互作用。每一个P元素的第一个字母是绿色的,字体尺寸为'24pt'。第一个格式行的其它部分是蓝色的,而段落的其它部分的颜色是'red'。
P { color: red; font-size: 12pt } P:first-letter { color: green; font-size: 200% } P:first-line { color: blue } <P>Some text that ends up on two lines</P>
假定在"ends"前有一个分行,那么这一片段的虚构标记序列为:
<P> <P:first-line> <P:first-letter> S </P:first-letter>ome text that </P:first-line> ends up on two lines </P>
注意,:first-letter元素在:first-line元素之内。设置在:first-line上的属性将为:first-letter继承,但是如果:first-letter设置了相同的属性,则继承的属性被超越。
':before'和':after'伪元素用来在一个元素的内容之前或之后插入生成的内容。它们的描述参见生成的内容一节。
H1:before {content: counter(chapno, upper-roman) ". "}
当:first-letter和:first-line伪元素与:before和:after相结合时,它们应用于包含插入的文本的第一个字母或第一行。
P.special:before {content: "Special! "} P.special:first-letter {color: #ffd800}
它将"Special!"中的"S"的颜色设置为金色。