5 选择器

内容

5.1 模式匹配

CSS中,模式匹配规则决定哪些样式规则将被应用于文档树中的元素,这些模式叫选择器,从简单的元素名到丰富的上下文模式(rich contextual patterns)。如果特定元素的模式中的所有条件都为真,则选择器匹配该元素

选择器中,文档语言元素名的大小写敏感性取决于文档语言,例如,HTML中,元素名是大小写不敏感的,但在XML中是大小写敏感的

下表总结了CSS 2.1选择器语法:

PatternMeaningDescribed in section
*匹配所有元素通配选择器
E匹配所有E元素(即,E类型的元素)类型选择器(标签选择器)
E F匹配所有E元素后代中的F元素后代选择器
E > F匹配所有E元素子级中的F元素子选择器
E:first-child匹配父元素的第一个子级为E的E元素(Matches element E when E is the first child of its parent) :first-child伪类
E:link
E:visited
匹配未访问过的(:link)或者已被访问过的(:visited)超链接源锚点(anchor)的E元素 link伪类
E:active
E:hover
E:focus
匹配处于某些用户动作期间的E元素 动态伪类
E:lang(c) 匹配语言为(人类)语言c的E元素(文档语言会指定怎样确定语言) :lang()伪类
E + F匹配所有前面紧跟着一个E元素兄弟的F元素相邻选择器
E[foo]匹配设置了"foo"属性(无论值是什么)的E元素 属性选择器
E[foo="warning"]匹配所有"foo"属性值恰好是"wraning"的E元素 属性选择器
E[foo~="warning"]匹配所有"foo"属性值为一列空格分隔的值,且其中之一恰好是"warning"的E元素 属性选择器
E[lang|="en"]匹配所有"lang"属性值为一列以"en"开头(从左向右)用连字符分隔的值的E元素 属性选择器
DIV.warning语言特定的(HTML中,与DIV[class~="warning"]相同 类选择器
E#myid匹配所有ID为"myid"的E元素ID选择器

5.2 选择器语法

简单选择器可以是类型选择器或者后面紧跟着一个或多个任意顺序的属性选择器ID选择器伪类通配选择器。简单选择器在其所有部分都匹配(成功)时才匹配(成功)

注意:这里用在CSS 2.1中的术语与用在CSS3中的不同,例如,“简单选择器”参考的CSS3选择器部分要比CSS 2.1更少。见CSS3选择器模块[CSS3SEL]

选择器是一串用连接符分隔的一个或者多个简单选择器。连接符是:空白字符,">"和"+"。空白字符可以出现在连接符和它前后的简单选择器之间

与选择器匹配的文档树元素叫做选择器的对象(subjects)。由一个简单选择器组成的选择器能够匹配满足其需求的任何元素。给一串(选择器)前面加上一个简单选择器和连接符就增加了额外的匹配约束,所以一个选择器的对象总是最后一个简单选择器匹配的元素的子集

一个伪元素可以被添加在一串选择器中最后一个简单选择器后面,此时样式信息会被应用在每个匹配元素的子内容(subpart )上

5.2.1 分组

当几个选择器共享相同的声明时,它们可以放进用逗号分隔的列表里

示例:

本例中,我们把三条有相同声明的规则压缩成一条,因此

h1 { font-family: sans-serif }
h2 { font-family: sans-serif }
h3 { font-family: sans-serif }

等价于:

h1, h2, h3 { font-family: sans-serif }

CSS还提供了其它“简写”机制,包括(一次)声明多条(规则)简写属性

5.3 通配选择器

通配选择器写作"*",匹配任意元素类型名。匹配文档树中的任意一个元素

如果通配选择器不是简单选择器的唯一组成部分(即选择器不为"*"),"*"可以省略,例如:

5.4 类型选择器

类型选择器匹配文档语言元素类型名。一个类型选择器会匹配文档树中所有该元素类型的实例

示例:

下列规则匹配文档树中的所有H1元素:

h1 { font-family: sans-serif }

5.5 后代选择器

有时,编写者可能想要选择器匹配一个在文档树中作为另一个元素后代的元素(例如,“匹配那些被H1元素包起来的EM元素”),后代选择器把这种关系用模式来表达。一个后代选择器由两个或者多个被空白字符隔开的选择器组成。一个形如"A B"的后代选择器匹配一个元素B,只要它是祖先元素A的任意后代

示例:

例如,考虑下面的规则:

h1 { color: red }
em { color: red }

尽管这些规则的目的都是通过改变颜色来给文本添加强调,但效果会在这种情况下消失:

<H1>This headline is <EM>very</EM> important</H1>

对于这种情况,我们通过用一条设置文本颜色为蓝色的规则来补充之前的规则来解决,无论EM出现在H1内的哪个位置:

h1 { color: red }
em { color: red }
h1 em { color: blue }

第三条规则将会匹配下列片段中的EM:

<H1>This <SPAN class="myclass">headline 
is <EM>very</EM> important</SPAN></H1>

示例:

下列选择器:

div * p 

匹配一个孙级或者DIV元素更后面的后代P元素。注意,"*"的前后的空白字符不是通配选择器的一部分,空白字符是一种连接符,表示DIV必须是某些元素的祖先并且那些元素还必须是P元素的祖先

示例:

下列规则中结合了后代和属性选择器的选择器,匹配(1)具有"href"属性集并且(2)位于本身位于DIV内部的P的内部的任意元素:

div p *[href]

5.6 子选择器

子选择器匹配一个作为某些元素的子级的元素。子选择器由两个或者更多用">"分隔的选择器组成

示例:

下面的规则设置了所有作为BODY子级的P元素的样式:

body > P { line-height: 1.3 }

示例:

下面的示例结合了后代选择器和子选择器:

div ol>li p

它匹配一个作为LI后代的的P元素,这个LI元素必须是一个OL元素的子级,OL元素必须是一个DIV的后代。注意,连接符">"前后可选的空白字符被删掉了

关于选择元素的第一个子级的更多信息请查看下面的:first-child伪类小节

5.7 相邻兄弟选择器

相邻兄弟选择器语法如下: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 }   

5.8 属性选择器

CSS 2.1允许编写者指定规则来匹配那些在源文档中定义了某些属性的元素

5.8.1 匹配属性与属性值

属性选择器可以通过4种方式匹配:

[att]
当元素设置了"att"属性时匹配,无论该属性的值是什么
[att=val]
当元素的"att"属性值恰好是"val"时匹配
[att~=val]
代表一个有att属性且值是一个由空白字符分隔的单词列表,其中之一恰好是"val"的元素。如果"val"含有空格,就不代表任何东西(因为单词是用空格分隔的)。如果"val"是个空字符串,它将同样不代表任何东西
[att|=val]
代表一个有att属性且值 ,要么是以"val"开头后面紧跟着"-"(U+002D)的元素。这主要是为了允许语言子码(language subcode)按照BCP 47([BCP47])或者其后续版本进行匹配(例如,HTML中a元素的hreflang属性)。关于lang(或者xml:lang)语言子码匹配,请查看:lang伪类

属性值必须是标识符或者字符串,选择器中属性名和值的大小写敏感性取决于文档语言

示例:

例如,下列属性选择器匹配所有指定了"title"属性的元素,无论值是什么:

h1[title] { color: blue; }

示例:

下例中,选择器匹配所有"class"属性值恰好是"example"的SPAN元素:

span[class=example] { color: blue; }

多个属性选择器可以用来引用同一个元素的几个属性,或者甚至把同一个属性引用多次

示例:

下面的选择器匹配所有"hello"属性值恰好是"Cleveland"并且"goodbye"属性值恰好是"Columbus"的SPAN元素:

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 }

示例:

下面的规则将匹配"lang"属性值以"en"开头,包括"en","en-US"和"en-cockney":

*[lang|="en"] { color : red }

示例:

类似的,下列听觉样式表(aural style sheet)规则能让剧本(script)中的每个角色(对白)用不同的声音读出来:

DIALOGUE[character=romeo] 
     { voice-family: "Laurence Olivier", charles, male }
      
DIALOGUE[character=juliet]  
     { voice-family: "Vivien Leigh", victoria, female }

5.8.2 文档类型定义(DTD)中的默认属性值

属性匹配是针对文档树中的属性值的。默认属性值可以定义在DTD里或者其它地方,但不一定能被属性选择器匹配到。样式表应该设计成在文档树中不含默认值时也能正常工作

更精确的,UA可以但不需要读取DTD的“外部子集(external subset)”,但需要在文档的“内部子集(internal subset)”中查找默认属性值(这些子集的定义见[XML10])。DTD外部子集中定义的默认属性值在文档树中出现与否,取决于UA

能识别XML命名空间[XMLNAMESPACES]的UA,可以但不必须用命名空间相关的信息来处理默认属性值,就像这些信息来自文档一样(例如,XHTML UA不必使用其内置的XHTML DTD相关信息)

注意,典型地,实现选择忽略外部子集

示例:

示例:

例如,考虑一个具有默认值为"decimal"的"notation"属性的EXAMPLE元素,DTD片段可能是

<!ATTLIST EXAMPLE notation (decimal,octal) "decimal">

如果样式表含有下列规则

EXAMPLE[notation=decimal] { /*... default property settings ...*/ }
EXAMPLE[notation=octal]   { /*... other settings...*/ }

第一条规则不会匹配"notation"属性被置为默认值的元素,即没有显式地设置。为了包括所有情况,针对默认值的属性选择器必须要删掉:

EXAMPLE                   { /*... default property settings ...*/ }
EXAMPLE[notation=octal]   { /*... other settings...*/ }

因为选择器EXAMPLE[notation=octal]比单独的类型选择器更具体,对于具有值为"octal"的"notation"属性的元素,第二条规则中的样式声明将会重写第一条。必须小心所有仅被应用于默认情况的属性声明会被非默认情况的样式规则重写

5.8.3 类选择器

HTML中,表示class属性的话,编写者可以把句号(.)符号作为~=符号的替代品。因此,对于HTML,div.valuediv[class~=value]具有相同的含义。属性值必须紧跟在“句号”(.)后面。UA可以在XML文档中把句号(.)符号用于选择器,如果UA有特定命名空间信息允许它决定各个命名空间下哪个属性是"class"属性。这种特定命名空间信息的示例在针对特殊命名空间的规范(例如,SVG 1.1 [SVG11]描述了SVG "class"属性以及UA应该怎样解释它,类似的,MathML 3.0 [MATH30]描述了MathML "class"属性)中有

示例:

例如,我们给所有具有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"值的一个子集,每个值前面必须要有一个"."

示例:

例如,下列规则匹配所有"class"属性被赋值为一列空格分隔的含有"pastoral"和"marine"的值:

 
p.marine.pastoral { color: green }

该规则匹配class="pastoral blue aqua marine"但不匹配class="pastoral blue"

注意:CSS赋予了"class"属性非常多的能力,编写者可以在与表现几乎无关的元素(例如,HTML中的DIV和SPAN)上设计他们自己的“文档语言”,并通过"class"属性来设置样式信息。编写者应该避免这种实践,因为文档语言的结构化元素通常具有可识别和可接受的含义,而编写者定义的class没有

注意:如果一个元素具有多个class属性,搜索class之前,它们的值必须用空格连接起来。目前,工作组对这种情况能被达成的方式并不明确,所以本规范中,这种行为显然是非规范的

5.9 ID选择器

文档语言可以含有被声明为ID型属性。ID型属性的特殊之处是没有两个这种属性可以有相同的值。无论在什么文档语言中,一个ID属性都可以被用作其元素的唯一标识。HTML中,所有ID属性都叫"id",XML应用程序可以命名不同的ID属性,但会受到同样的限制

文档语言的ID属性允许编写者给文档树中的一个元素实例设置一个标识符。CSS ID选择器根据它的标识符匹配一个元素实例。一个CSS ID选择器包含"#"和后面紧跟着的ID值,该值必须是一个标识符

注意,CSS没有指定UA如何获知一个元素的ID属性。UA可能会,例如,读取文档的DTD,含有的硬编码信息或者询问用户

示例:

下列ID选择器匹配ID属性值为"chapter1"的H1元素:

h1#chapter1 { text-align: center }

下例中,样式规则匹配ID值为"z98y"的元素,因此,该规则将匹配P元素:

<HEAD>
  <TITLE>Match P</TITLE>
  <STYLE type="text/css">
    *#z98y { letter-spacing: 0.3em }
  </STYLE>
</HEAD>
<BODY>
   <P id=z98y>Wide text</P>
</BODY>

下一个示例中,样式规则将只匹配一个ID值为"z98y"的H1元素,该规则不会匹配本例中的P元素:

<HEAD>
  <TITLE>Match H1 only</TITLE>
  <STYLE type="text/css">
    H1#z98y { letter-spacing: 0.5em }
  </STYLE>
</HEAD>
<BODY>
   <P id=z98y>Wide text</P>
</BODY>

ID选择器比属性选择器的特殊性更高。例如,HTML中,根据层叠,选择器#p123[id=p123]更具体

注意 在XML 1.0[XML10]中,关于含有元素ID的属性的信息被包含在DTD中。当解析XML时,UA并不总会读取DTD,并且因此可能不知道一个元素的ID是什么。如果一个样式表设计者知道或者怀疑这种情况,他应该用常规属性选择器代替:[name=p371]而不是#p371。然而,常规属性选择器的层叠顺序与ID选择器不同,可能有必要给声明添上一个"!important"优先级:[name=p371]{color: red ! important}

如果一个元素有多个ID属性,鉴于ID选择器的目的,它们必须全部都被当作这个元素的ID。这种情况可以通过使用id[XMLID],DOM3 Core [DOM-LEVEL-3-CORE],XML DTDs [XML10]和特定命名空间信息(namespace-specific knowledge)的混合(mixtures)来实现

5.10 伪元素伪类

CSS 2.1中,样式通常是根据元素在文档树中的位置添加的。这种简单模型在大多数情况下足够了,但在有些常见的排版场景下可能无法根据文档树的结构(添加样式)。例如,HTML 4(见[HTML4])中,没有元素对应的是一个段落的第一行,所以简单CSS选择器无法引用它

为了允许根据文档树之外的信息来格式化,CSS引入了伪元素伪类的概念

伪元素和伪类都不会出现在源文档或者文档树中

伪类允许出现在选择器的任何位置,而一个伪元素只能跟在选择器的最后一个简单选择器后面

伪元素名和伪类名都是大小写不敏感的

有些伪类是互斥的,而其它的可以同时用在一个元素上。在规则冲突的情况下,常规层叠顺序决定结果

5.11 伪类

5.11.1 :first-child伪类

:first-child伪类匹配一个作为某个其它元素的第一个子级的元素

示例:

下例中,选择器匹配所有作为DIV元素的第一个子级的P元素。规则禁止DIV中的第一个段落缩进:

div > p:first-child { text-indent: 0 }
该选择器将匹配下面片段中DIV里的P:
<P> The last P before the note.
<DIV class="note">
   <P> The first P inside the note.
</DIV>
但不会匹配下面片段中的第二个P:
<P> The last P before the note.
<DIV class="note">
   <H2>Note</H2>
   <P> The first P inside the note.
</DIV>

示例:

下面的规则把所有作为第一个子级P元素的后代中的EM元素的字重(font weight)设置为'bold':

p:first-child em { font-weight : bold }

注意,因为匿名盒不是文档树的一部分,计算第一个子级时不算它们

例如,EM在

<P>abc <EM>default</EM> 
中是P的第一个子级

下列两个选择器是等价的:

* > a:first-child   /* A is first child of any element */
a:first-child       /* Same */

5.11.2 link伪类:link:visited

用户代理通常把未访问过的链接和已访问过的区分显示。CSS提供了伪类':link'和':visited'来区分它们:

UA有时会让一个访问过的链接回到(未访问的)':link'状态

这两种状态是互斥的

文档语言决定了哪些元素是超链接源锚点(anchor)。例如,HTML4中,link伪类适用于带有"href"属性的A元素。因此,下列两条CSS 2.1声明的效果相似:

a:link { color: red }
:link  { color: red }

示例:

如果下面的链接:

<A class="external" href="http://out.side/">external link</A>
已经被访问过了,这条规则:
a.external:visited { color: blue }
将让它变蓝

注意,样式表编写者可能滥用:link和:visited伪类,来确定用户已经曾访问过哪些站点,而不经用户同意

因此,UA可以把所有链接都当作未被访问过的链接,或者在分别渲染访问过的和未访问过的链接时,采取其它措施来保护用户的隐私。关于处理隐私的更多信息请查看[P3P]

5.11.3 动态伪类: :hover:active:focus

交互式用户代理有时会改变渲染(效果)以响应用户动作。对于一般情况,CSS提供了三个伪类:

一个元素可以同时匹配几个伪类

CSS没有定义哪些元素可以处于上面的状态,以及这些状态怎样进入和离开。脚本(执行)可以改变元素是否对用户事件做出响应,并且不同的设备和UA指向和激活元素的方式可能也不相同

CSS 2.1没有定义':active'或者':hover'元素的父级是不是也处于这种状态

用户代理不必因为伪类转变而重排(reflow)当前显示的文档。例如,一个样式表可以指定:active链接的'font-size'比非激活状态的链接大,但因此会导致字母在读者选中链接时改变位置,UA可以忽略相关样式规则

示例:

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后面,用户激活并悬停在A元素上时,将会应用激活态的颜色(lime)

示例:

结合了动态伪类的示例:

a:focus { background: yellow }
a:focus:hover { background: white }

最后一个选择器匹配处于伪类:focus和伪类:hover(状态)的A元素

关于展示焦点轮廓(focus outline)的更多信息,请查看动态焦点轮廓章节

注意 CSS1中,':active'伪类与':link'和':visited'是互斥的,而现在情况不一样了。一个元素可以同时处于':visited'和':active'(或者':link'和':active'),由常规层叠规则决定应用哪个样式声明

注意 CSS1中,':active'伪类只会应用于链接

5.11.4 语言伪类: :lang

如果文档语言指定了怎样定义一个元素的人类语言(human language),就有可能用CSS写出选择器根据元素的语言来匹配一个元素。例如,HTML[HTML4]中,语言是由"lang"属性,META元素以及可能的来自协议的信息(例如,HTTP头)结合起来决定的。XML用一个叫xml:lang的属性和可能的其它文档特定语言的方法来确定语言

伪类':lang(C)'匹配语言为C的元素。是否存在匹配,仅仅根据标识符C等于元素的语言值或者是连字符分隔元素的语言值的子串来确定。同样的,就像'|='操作符一样。C与元素语言值的匹配过程对ASCII范围内的字符是大小写不敏感的。标识符C不一定是一个合法的语言名

C不能为空

注意:建议文档和协议通过BCP 47 [BCP47]码或者其后续版本指出语言,而基于XML的文档[XML10]则用"xml:lang"属性。见“FAQ:两个字母或三个字母的语言码”

示例:

下列规则给一个加拿大法语或德语HTML文档设置引号:

html:lang(fr-ca) { quotes: '« ' ' »' }
html:lang(de) { quotes: '»' '«' '\2039' '\203A' }
:lang(fr) > Q { quotes: '« ' ' »' }
:lang(de) > Q { quotes: '»' '«' '\2039' '\203A' }

第二对规则实际上给Q元素根据其父级的语言设置了'quotes'属性。能这样做是因为引号是根据引号周围元素的语言选择的,而不是引号本身:比如这段英语文本中的法语“à l'improviste”用的是英文引号

注意 [lang|=xx]和:lang(xx)的区别。在该HTML示例中,只有BODY匹配[lang|=fr](因为它有LANG属性),但BODY和P都匹配:lang(fr)(因为都是法语)

<body lang=fr>
  <p>Je suis Français.</p>
</body>

5.12 伪元素

伪元素的行为就像CSS中的真实元素一样,但存在下面描述的以及其它的例外

注意,下面的小节没有定义严格的对':first-line'和':first-letter'的渲染,将来的CSS版本可能会精确地定义它们

5.12.1 :first-line伪元素

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可能会被用户代理“重写”成含有虚拟标签序列(fictional tag sequence)的形式,这种虚拟标签序列有助于展示属性的继承方式,可能会被用户代理“重写”:

<P><P:first-line> This is a somewhat long HTML 
paragraph that </P:first-line> 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>

如果伪元素把一个真实元素拆开了,想要的效果是由虚拟标签序列闭合再重新打开该元素。因此如果我们用一个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伪元素只能用于块容器元素

元素的"第一个格式化行"可能出现在相同流(flow)中的一个块级后代(即一个没有被定位且不浮动的块级后代)里面。例如,<DIV><P>This line...</P></DIV>中DIV的第一行是P的第一行(假设P和DIV都是块级的)

表格单元或者inline-block的第一行不能作为祖先元素第一个格式化行。因此,在<DIV><P STYLE="display: inline-block">Hello<BR>Goodbye</P> etcetera</DIV>中,DIV的第一个格式化行不是"Hello"

注意,<p><br>First...中P的第一行不包含任何字母(假设是HTML 4中BR默认样式表)。单词"First"不在第一个格式行内

UA应该表现的就像first-line伪元素的虚拟开始标签嵌套在最内层的闭合块级元素中(因为CSS1和CSS2都没有说明这种情况,编写者不应该依赖这种行为),例如:

<DIV>
  <P>First paragraph</P>
  <P>Second paragraph</P>
</DIV>

虚拟标签序列为

<DIV>
  <P><DIV:first-line><P:first-line>First paragraph</P:first-line></DIV:first-line></P>
  <P><P:first-line>Second paragraph</P:first-line></P>
</DIV>

:first-line伪元素与行内元素类似,但存在一些限制。下列属性适用于:first-line伪元素:font属性color属性background属性'word-spacing''letter-spacing''text-decoration''text-transform''line-height'。UA还可能应用其它属性

5.12.2 :first-letter伪元素

:first-letter伪元素必须选择一个块的第一行的第一个字母,如果这一行中在它前面没有跟着任何其它内容(例如,图片或者inline table)的话。:first-letter伪元素可以用于“首字母大写(initial caps)”“首字母下沉(drop caps)”之类的常见排版效果。此类首字母与'float'属性为'none'的行内元素或者浮动元素类似

适用于:first-letter伪元素的属性有: font属性'text-decoration''text-transform''letter-spacing''word-spacing'(在合适的时候), 'line-height''float''vertical-align'(仅当'float'为'none'时), margin属性padding属性border属性color属性background属性。 UA还可能会应用其它规则。为了让UA正确渲染首字母下沉或者首字母大写排版,UA可以根据字母的形状选择行高,宽度和高度,这与常规元素不同。预期CSS3会有适用于首字母的具体属性

本例展示了一个可能的首字母大写渲染,注意,first-letter伪元素继承的'line-height'是1.1,但本例中UA特别计算了首字母的高度,因此它不会导致前两行之间有任何不必要的空隙。还要注意,首字母的虚拟开始标签在SPAN里面,因此首字母的字重是正常的,而不是和SPAN一样的粗体:

p { line-height: 1.1 }
p:first-letter { font-size: 3em; font-weight: normal }
span { font-weight: bold }
...
<p><span>Het hemelsche</span> gerecht heeft zich ten lange lesten<br>
Erbarremt over my en mijn benaeuwde vesten<br>
En arme burgery, en op mijn volcx gebed<br>
En dagelix geschrey de bange stad ontzet.

Image illustrating the :first-letter pseudo-element

下列CSS 2.1(规则)将会让首字母下沉大约两行:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML>
 <HEAD>
  <TITLE>Drop cap initial letter</TITLE>
  <STYLE type="text/css">
   P              { font-size: 12pt; line-height: 1.2 }
   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>

本例可能被格式化为这样:

Image illustrating the combined effect of the :first-letter and :first-line pseudo-elements   [D]

虚拟标签序列为:

<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伪元素的开始标签紧跟在块元素开始标签之后

为了达到传统首字母下沉的格式化效果,用户代理可以用近似字体大小,例如为了对齐基线。另外,在格式化时,还可能会把字形轮廓考虑在内

(first-letter)应该包括紧跟在首字母前后的标点符号(即用Unicode [UNICODE]定义的"open" (Ps),"close" (Pe),"initial" (Pi),"final" (Pf)和"other" (Po)标点类字符),例如:

Quotes that precede the
first letter should be included.   [D]

首字母是数字的话,':first-letter'也同样适用,例如,"67 million dollars is a lot of money."中的"6"

:first-letter伪元素适用于块容器元素

:first-letter伪元素可以用于所有含有文本的元素,或者相同流(flow)中有含有文本的后代(元素)。UA应该表现得像first-letter伪元素的虚拟开始标签恰好在该元素的第一块文本内容之前,即使第一块文本内容位于后代元素中

示例:

例如,HTML片段

<div>
<p>The first text.

的虚拟标签序列为:

<div>
<p><div:first-letter><p:first-letter>T</...></...>he first text.

表格单元或者inline-block的首字母不能作为其祖先元素的首字母。因此,在<DIV><P STYLE="display: inline-block">Hello<BR>Goodbye</P> etcetera</DIV>中,DIV的首字母不是字母"H",实际上,该DIV没有首字母

首字母必须出现在第一个格式化行中,例如,片段:<p><br>First...中,第一行没有任何字母,那么':first-letter'不会匹配任何东西(假设是HTML 4中BR的默认样式)。这种情况下,它不会匹配"First"的"F"

如果一个元素是列表项('display: list-item'),':first-letter'适用于标记后面的主要盒中的首字母。 UA可以忽略具有'list-style-position: inside'的列表项上的':first-letter'(规则)。如果一个元素具有':before'或者':after'内容,':first-letter'应用于元素包括这些内容在内的第一个字母

例如,应用'p:before {content: "Note: "}'规则后,选择器'p:first-letter'会匹配"Note"的"N"

有些语言可能有关于怎样对待特定字母组合的具体规则,在荷兰,例如,如果字母组合"ij"出现在单词开头,这两个字母应该都属于:first-letter伪元素

如果将要作为first-letter的字母不再同一个元素中,例如<p>'<em>T...中的"'T",UA可能会从中取一个元素创建first-letter伪元素,或者都给创建伪元素,或者干脆不创建伪元素

类似的,如果块的首字母不在行开头(例如,由于双向重排序(bidirectional reordering)),那么UA不需要创建该伪元素

示例:

下例描述了伪元素互相重叠的情况。P元素的首字母将是绿色的,字体大小为'24pt'。第一个格式化行的其余部分将是'blue',而段落的其它部分将是'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的相同属性,则会被重写

5.12.3 :before:after伪元素

':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"渲染成金色