6 属性赋值,层叠(Cascading)和继承

内容

6.1 指定值,计算值和实际值

一旦用户代理已经解析了文档并构造好了文档树,它就必须给树中的每个元素上适用于目标媒体类型的每个属性赋值

属性的最终值是4步计算的结果:先通过指定来确定值(“指定值(specified value)”),接着处理得到一个用于继承的值(“计算值(computed value)”),然后如果有必要的话转化为一个绝对值(“应用值(used value)”),最后根据本地环境限制进行转换(“实际值(actual value)”)

6.1.1 指定值

用户代理必须先根据下列机制(按优先顺序)给每个属性赋值一个指定值:

  1. 如果层叠产生了一个值,就使用它
  2. 否则,如果属性是继承的并且该元素不是文档树的根元素,使用其父元素的计算值
  3. 否则使用属性的初始值,每个属性的初始值都在属性定义中指出了

6.1.2 计算值

指定值通过层叠被处理为计算值,例如,URI被转换成绝对的,'em'和'ex'单位被计算为像素或者绝对长度。计算一个值并不需要用户代理渲染文档

UA无法处理为绝对URI的话,该URI的计算值就是指定值

一个属性的计算值由属性定义中Computed Value行决定。当指定值为'inherit'时,计算值的定义见继承小节

即使属性不适用(于当前元素),其计算值也存在,定义在'Applies To'行。然而,有些属性可能根据属性是否适用于该元素来定义元素属性的计算值

6.1.3 应用值

处理计算值时,尽可能不要格式化文档。然而,有些值只能在文档布局完成时确定。例如,如果一个元素的宽度是其包含块的特定百分比,在包含块的宽度确定之前无法确定这个宽度。应用值是把计算值剩余的依赖(值)都处理成绝对值后的(计算)结果

6.1.4 实际值

原则上,应用值应该用于渲染,但用户代理可能无法在给定的环境中利用该值。例如,用户代理或许只能用整数像素宽度渲染边框,因此不得不对宽度的计算值做近似处理,或者用户代理可能被迫只能用黑白色调而不是全彩色。实际值是经过近似处理后的应用值

6.2 继承

有些值是从文档树中某个元素的子级继承来的,就像上面描述的一样。每个属性都定义了它是否可继承

假设H1元素里有个强调元素(EM):

<H1>The headline <EM>is</EM> important!</H1>

如果没有给EM元素赋值颜色,强调的"is"将从其父元素继承颜色,所以如果H1是蓝色的,EM元素同样也将是蓝色的

发生继承时,元素继承计算值。来自父元素的计算值同时作为指定值和其子级的计算值

示例:

例如,给出如下样式表:

body { font-size: 10pt }
h1 { font-size: 130% }

和文档片段:

<BODY>
  <H1>A <EM>large</EM> heading</H1>
</BODY>

H1元素的'font-size'属性将获得计算值'13pt'(130%乘以父元素的值10pt)。因为'font-size'的计算值是继承的,EM元素也将获得计算值'13pt'。如果用户代理没有可用的13pt字体,H1和EM的'font-size'的实际值可能是,例如,'12pt'

注意,继承遵循文档树并且不会被匿名框截断

6.2.1 'inherit'

每个属性也可能有一个'inherit'层叠值,表示对于一个给定的元素,属性采用与其父级属性相同的指定值。'inherit'值可以用来实现值的继承,并且它也可以用在那些一般不是继承的属性上

如果'inherit'值设置在根元素上,该属性会被赋值为其初始值

示例:

下例中,'color''background'属性被设置在BODY元素上。对于其它所有元素,'color'值都将被继承并且背景将是透明的。如果这些规则是用户样式表的一部分,整个文档都将是白色背景上的黑色文本

body {
  color: black !important; 
  background: white !important;
}

* { 
  color: inherit !important; 
  background: transparent !important;
}

6.3 @import规则

'@import'规则允许用户从其它样式表引入样式规则。CSS 2.1中,任何@import规则必须位于所有其它规则(除了@charset,如果有的话)之前。关于用户代理什么情况下必须忽略@import规则,见解析章节。'@import'关键字后面必须跟着想要引入的样式表的URI。字符串也可以接受,也可以表示成周围有url(...)的形式

示例:

下面这几行在意义上是等价的,都描述了'@import'语法(一个有"url()",另一个是裸字符串):

@import "mystyle.css";
@import url("mystyle.css");

为了让用户代理能够避免为不支持的媒体类型检索资源,编写者可以指定带媒体依赖(media-dependent)的@import规则。这种条件引入在URI后面指定了逗号分隔的媒体类型

示例:

下列规则描述了@import规则怎样变成带媒体依赖的:

@import url("fineprint.css") print;
@import url("bluish.css") projection, tv;

缺少媒体类型时,引入是无条件的,与把媒体指定为'all'效果一样。引入只在目标媒体匹配媒体列表时才生效

如果媒体列表中有一项是目标媒体或者'all'时,目标媒体匹配媒体列表

注意,媒体查询[MEDIAQ]扩展了媒体列表的语法和匹配的定义

引入相同样式表或者在多处链接同一文档时,用户代理必须处理(或者表现得像那样)每一个链接,就像链接都指向一个单独的样式表一样

6.4 层叠(cascade)

样式表可能有3种不同来源:编写者,用户和用户代理

这3种样式表将在一定范围内重叠,并且它们按照层叠互相影响

CSS层叠给每个样式规则赋予了权重。应用几条规则时,权重最大的优先

默认情况下,编写者样式表中的规则比用户样式表中的规则权重高。然而,对于"!important"规则,优先级却是相反的。所有用户和编写者规则都比UA默认样式表中的规则权重高

6.4.1 层叠顺序

为了找出一个元素/属性组合的值,用户代理必须按照下列(步骤)排序:

  1. 找出目标媒体类型下,所有适用于该元素和目标属性的声明。如果关联的选择器匹配该元素,并且目标媒体类型与含有该声明的@media规则列出的所有媒体类型,以及到达样式表的路径上所有链接匹配,则声明适用(Declarations apply if the associated selector matches the element in question and the target medium matches the media list on all @media rules containing the declaration and on all links on the path through which the style sheet was reached.)
  2. 根据重要性(常规或重要)和来源(编写者,用户或用户代理)排序,升序优先级为:
    1. 用户代理声明
    2. 用户常规声明
    3. 编写者常规声明
    4. 编写者重要声明
    5. 用户重要声明
  3. 相同重要性和来源的规则根据选择器的特殊性(specificity)排序:更特殊的选择器将重写一般的。伪元素和伪类被分别算作常规元素和类
  4. 最后,根据指定顺序排序:如果两个声明的权重,来源和特殊性都相同,后指定的生效。引入的样式表(译注:这里应该是指'@import',而不是广义的通过各种方式引入样式表)中的声明被认为在样式表自身的所有声明之前

除了给个别声明设置"!important"外,比起读者样式表,这种策略给了编写者样式表更高的权重。用户代理必须给予用户去除特定编写者样式表影响的能力,例如,通过一个下拉菜单。与UAAG 1.0 checkpoint 4.14一致的(用户代理)满足该条件[UAAG10]

6.4.2 !important规则

CSS尝试在编写者和用户样式表之间建立平衡。默认情况下,编写者样式表中的规则会重写那些位于用户样式表中的(见层叠规则3)

然而,为了平衡,"!important"声明(声明后面跟着分隔符token "!"和关键字"important")比常规声明优先。编写者和用户样式表都可能含有"!important"声明,并且用户"!important"规则会重写编写者"!important"规则。通过给予用户表现上的特殊需求(大字体,颜色组合等等)控制,该CSS特性提高了文档的可访问性

声明一个简写属性(例如,'background')为"!important"等价于声明其所有子属性为"!important"

示例:

下例中用户样式表的第一条规则含有一个"!important"声明,重写了编写者样式表中的相关声明。第二条声明也将生效,因为被标记为"!important"了。然而,用户样式表中的第三条规则不是"!important",因此被编写者样式表(恰好在一条简写属性中设置了)中的第二条规则重写了。而且,第三条编写者规则将被第二条编写者规则重写,因为第二条规则是"!important"。这说明"!important"声明在编写者样式表中也有效

/* From the user's style sheet */
p { text-indent: 1em ! important }
p { font-style: italic ! important }
p { font-size: 18pt }

/* From the author's style sheet */
p { text-indent: 1.5em !important }
p { font: normal 12pt sans-serif !important }
p { font-size: 24pt }

6.4.3 计算选择器的特殊性(specificity)

一个选择器的特殊性是根据下列(规则)计算的:

特殊性只根据选择器的形式来定。特殊的,一个"[id=p33]"形式的选择器被算作一个属性选择器(a=0, b=0, c=1, d=0),即使id属性在源文档的DTD中被定义为"ID"

4个数连起来a-b-c-d(在一个基数很大的数字系统中(in a number system with a large base))表示特殊性

示例:

一些示例:

 *             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */
 li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */
 li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
 ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */
 ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */
 h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */
 ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */
 li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */
 #x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */
 style=""          /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */
<HEAD>
<STYLE type="text/css">
  #x97z { color: red }
</STYLE>
</HEAD>
<BODY>
<P ID=x97z style="color: green">
</BODY>

上面的示例中,P元素的颜色将是绿色,"style"属性中的声明将重写STYLE元素中的,因为层叠规则3,它的特殊性更高

6.4.4 非CSS表现型提示(presentational hints)的样式优先级

UA可能选择尊重HTML源文档中的表现型属性。如果这样的话,这些属性会被翻译成相应的特殊性为0的CSS规则,并且就当它们像是被插在编写者样式表开头的一样。因此,它们可以被后续样式表符规则重写。在过渡阶段,这种策略让表现型属性(stylistic attributes)更容易与样式表共存

对于HTML,下面列表之外的任何属性都应该被认为是表现性的:abbr,accept-charset,accept,accesskey, action,alt,archive,axis,charset,checked,cite,class,classid, code,codebase,codetype,colspan,coords,data,datetime,declare, defer,dir,disabled,enctype,for,headers,href,hreflang, http-equiv,id,ismap,label,lang,language,longdesc,maxlength, media,method,multiple,name,nohref,object,onblur,onchange, onclick,ondblclick,onfocus,onkeydown,onkeypress,onkeyup,onload, onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup, onreset,onselect,onsubmit,onunload,onunload,profile,prompt, readonly,rel,rev,rowspan,scheme,scope,selected,shape,span, src,standby,start,style,summary,title,type(LI,OL和UL元素上的除外),usemap,value,valuetype,version

对于其它语言,所有基于文档语言的样式必须被翻译成相应的CSS,并且要么算进用户代理级的层叠中,要么与HTML表现型提示一起被当作特殊性为0的编写者级规则放在编写者样式表开头

示例:

下列用户样式表将会重写所有文档中'b'元素的字重,以及XML文档中具有color属性的font'元素的颜色。它将不会影响HTML文档中任何具有color属性的'font'元素的颜色(译注:实际上,在HTML里这个样式对有color属性的font元素也是有效的。但一致性章节有声明“示例和注意事项是非规范的”,这里是示例):

b { font-weight: normal; }
font[color] { color: orange; }

然而,下面的(样式表)将会重写所有文档中font元素的颜色:

font[color] { color: orange ! important; }