Warning:
This wiki has been archived and is now read-only.

CSS2/cascade

From HTML5 Chinese Interest Group Wiki
Jump to: navigation, search

分派属性值、层叠与继承

内容概要

指定值、计算值与实际值

用户代理在解析文档并建构文档树之后,必须为树中每一个元素的每一个属性分派一个适用于目标媒体类型的属性值。

属性的最终取值是经过四步计算得出的结果:由文档指定的取值(「指定值」),经过处理得到可被直接继承的取值(「计算值」),再在必要的时候转化成绝对值(「使用值」),最后根据本地环境的限制转换成最终值(「实际值」)。

指定值
Error creating thumbnail: Unable to save thumbnail to destination

用户代理必须先根据以下机制(按优先次序)为每一个属性分派指定值:

  1. 若通过层叠得到一个值,且该值不是 'inherit'
    Error creating thumbnail: Unable to save thumbnail to destination
    ,则使用这个取值。
  2. 否则,若得到的值是 'inherit',且元素不是文档树的根,则使用父元素的计算值。
  3. 否则使用属性的初始值。每个属性的初始值都被记载在该属性的定义表格中。

计算值

指定值在层叠的时候经处理变成计算值,举例来说,把URI都解析成绝对URI,把以'em'和'ex'为单位的值计算成像素值或是绝对长度。计算这些取值不需要对文档进行渲染。

若用户代理不能把某个URI解析成绝对URI,则计算值仍为原指定值。

属性的指定值由属性定义表格中「计算值:」这一栏指定的方法来决定。
Error creating thumbnail: Unable to save thumbnail to destination

就算根据「适用于:」这一栏的定义,一个属性为对某个元素不适用,但其计算值仍然存在。然而,也有些属性会根据该属性是否适用于某个元素来决定元素属性的计算值。

使用值

计算值是在不对文档进行排版的情况下,以最快速度处理得到的结果。然而,有些值只能在文档排版的时候才能决定。举例来说,如果一个元素的宽度设为其包含块的某个百分比,那么在决定其包含块的宽度之前,这个元素的宽度就不能决定。使用值是解决了剩下的依赖关係之后,计算出来的绝对值。

实际值

原则上,使用值就是渲染时所采用的取值。但是在特定的环境下,用户代理可能无法使用这个值。举例来说,用户代理可能只能渲染整数像素宽的边框,因此只能近似地计算宽度,又或者用户代理可能被迫只能用黑白两色而不是真彩色。实际值是用户代理对使用值经过近似处理之后的结果。

继承

如同上面所述,一个文档树中一个元素的有些属性值会被其子元素继承。每个属性的属性定义表格分别描述了该属性会被继承与否。

假设有一个 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'(举例来说)。
注:请注意继承是透过文档树进行的,匿名盒不会截取继承。

'inherit' 值

每一个属性都可以有 'inherit' 作为层叠值。'inherit' 表示给定元素的指定值是该元素父元素的计算值
Error creating thumbnail: Unable to save thumbnail to destination
。'inherit' 值可以用来强迫取值的继承发生,也可以用在一般不继承的属性上。 若根元素的某个属性设有 'inherit' 值,用户代理会把属性的初始值指派给该属性
Error creating thumbnail: Unable to save thumbnail to destination
在下面的范例中,BODY 元素设有 'color''background' 属性。对于其他元素,'color' 的取值会继承且底色会是透明的。在用户样式表的一部分使用这些规则等于是迫使整份文档以白底黑字呈现。
body {
  color: black !important; 
  background: white !important;
}

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

@import 规则

'@import' 规则允许用户从其它样式表中导入样式。在 CSS2.1,@import 规则必须写在其它规则前面(@charset规则除外)。请见样式解析这章,以了解用户代理何时必需忽略 @import 规则。'@import' 关键字必需跟着要被导入的样式表URI或一个字符串。当'@import' 关键字跟着一个字符串时,此字符串会当成被url(...)包围着来解析。

以下两行以 "url()" 的方式和纯字符串的方式分别示范了 '@import' 规则的语法,其效果是一样的:
@import "mystyle.css";
@import url("mystyle.css");

作者可指定限定媒体的 @import 规则,以避免用户代理为不支持的媒体去获取资源。这种条件导入的规则在 URI 后面指定了以逗号分隔的媒体列表。

以下规则示范如果让 @import 规则变成限定媒体的规则:
@import url("fineprint.css") print;
@import url("bluish.css") projection, tv;

仅当目标媒体与指定的媒体列表相匹配时,才会将规则导入。若没有指定媒体,或指定 'all' 作为媒体,则规则会被无条件导入。

当媒体列表中的一个条目与目标媒体相同或为 'all' 时,就说一个目标媒体与媒体列表匹配。

注:请注意媒体队列 [MEDIAQ] 扩展了媒体列表的语法和关于匹配的定义。

如果同一个样式表被同一个文档导入或引用了多次,则用户代理必须像对待不同的样式表那样对每次引用都依次处理一遍。

层叠

样式表有三种不同的来源:网页作者、用户、用户代理。

  • 网页作者:作者根据网页文档编写语言的特性为网页源文件指定了样式表。例如,在HTML,可以把样式表内嵌在文档中或通过链接来引用外部样式表。
  • 用户:用户可以对特定文档指定样式信息。例如,用户可以指定一个包含样式表的文件,也可以由用户代理提供一个接口(或者类似的形式)来生成用户样式表。
  • 用户代理:符合规范的用户代理必须启用一个预设样式表(或者表现得像有这么一回事)。用户代理的预设样式表应该以满足文档语言一般期望的显示方式来呈现各元素(例:视觉浏览器以斜体的字形来呈现 HTML 中的 EM 元素)。请参考本规范对 HTML 文档建议的预设样式 —— 「一个 HTML 的样本样式表」
注:请注意:用户可以通过修改系统设置(例如:系统颜色)的方式来影响预设样式表。但是,部分用户代理的实现方式导致用户无法改变预设样式表中的值。

这三种来源的样式表会在网页范围内有所重叠,他们会按照层叠的方式产生相互影响。

CSS层叠会赋予每条样式规则一个权重。当几条规则同时生效时,权重最大的规则优先。

通常,网页作者指定的样式表权重高于用户样式表,再高于用户代理的预设样式表。但对于指定了 '!important' 的规则,优先次序是正好反过来。

层叠次序

用户代理必须使用下面的排序方式找找出一个元素的属性值:

  1. 为目标媒体类型找出所有适用于目标元素与属性的所有声明。当声明对应的选择器匹配目标元素,且目标媒体匹配包含此声明的 @media 规则构成的媒体列与到达该样式表的路径上的所有媒体列,则本规范称该声明适用于目标元素与属性。
  2. 按以下优先度递增的次序根据重要性(一般或重要)和来源(网页作者、用户或用户代理)来排序:
    1. 用户代理声明
    2. 用户一般声明
    3. 网页作者一般声明
    4. 网页作者重要声明
    5. 用户重要声明
  3. 对有相同重要性与来源的规则,按特异度来排序:比较特异的选择器会覆盖比较一般的。伪元素与伪类别分别以一般元素与一般类别计算。
  4. 最后,按声明出现的顺序来排序:若两个声明有相同的重要性、来源与特异度,则后出现的优先度较高。在被导入样式表中出现的声明相当于出现在当前样式表中任何声明之前。
除了可将个别声明设为 "!important"之外,该策略还可给予网页作者样式表比读者提供的样式表更高的优先度。用户代理必须为用户提供取消某个特定网页作者样式的能力,例:透过下拉式选单。通过 UAAG 1.0 的检查点 4.14 即可满足这个条件。[UAAG10]
Error creating thumbnail: Unable to save thumbnail to destination

!important 规则

CSS 尝试在网页作者样式表与用户样式表之间取得权力的平衡。通常,网页作者样式表会覆盖用户样式表(参见层叠规则 3)。

然而,为求平衡,"!important" 声明的优先顺序在一般宣告之前。"!important" 声明就是在声明后面接一个 DELIM token "!" 和关键字 "important"。网页作者与用户样式表皆可含有 "!important" 声明,而用户 "!important" 声明会覆盖网页作者 "!important" 声明。这个 CSS 特性给予了用户一种控制方法来限制网页作者选择的呈现方式,以便实现一些特殊要求(例如:大一点的字型、颜色组合等等),从而改进了文档可读性。

声明缩写属性(如:'background')为 "!important" 等同于宣告缩写属性的所有子属性为 "!important"。

下面范例中的用户样式表的第一个规则有一个 "!important" 宣告,覆盖了网页作者样式表的对应宣告。第二个宣告也因为有 "!important" 标记获得优先。然而,用户样式表的第三个规则不是 "!important",因此优先度不及网页作者样式表的(使用缩写设定样式的)第二个规则。另外,因为第二个网页作者规则为 "!important",第三个网页作者规则的优先度也输给第二个规则,这说明 "!important" 宣告同样在网页作者样式表里也有作用。
/* 以下是用户样式表的一部分 */
p { text-indent: 1em ! important }
p { font-style: italic ! important }
p { font-size: 18pt }

/* 以下是网页作者样式表的一部分 */
p { text-indent: 1.5em !important }
p { font: normal 12pt sans-serif !important }
p { font-size: 24pt }

计算选择器的特异度

根据以下方法来计算一个选择器的特异度:

  1. 让(a=)1,如果该声明是在一个元素style属性值中出现;否则为0,即该声明是在有选择器的样式规则中出现。(在 HTML, 元素style属性的值也是一个样式表的规则。这类规则没有选择器,因此,a=1, b=0, c=0, and d=0.)
  2. 让(b=)选择器中ID属性的数量
  3. 让(c=)选择器中其它属性和虚拟类型的数量
  4. 让(d=)选择器中元素名和虚拟元素的数量

特异度仅与选择器的结构有关。举个特例:即使在源文档的DTD中id属性被定义为元素的ID,形如 '[id=p33]' 的选择器也只会被当成一个属性选择器 (a=0, b=0, c=1, d=0),而不是ID选择器 (a=0, b=1, c=0, d=0)

把a-b-c-d这四个数字连接起来就组成了选择器的特异度。

Some examples:
 *             {}  /* 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的颜色应该是绿色。根据层叠规则3,在style属性中的声明会覆盖在STYLE元素中的声明,因为前者的特异度较高。

与呈现方式相关的非 CSS 说明信息生效的优先次序

用户代理可选择跟随HTML源文件中与呈现方式相关的属性。如果是这样,这些属性会被转换成特异度为0的对应 CSS 规则,并当成把这些规则的声明插入到网页作者样式表的开始位置来处理。因此,它们会被后继的样式表规则覆盖。在转换过程中,这种策略会使式样相关的属性较容易地与样式表的效果并存。

以 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。

对于其它语言,所有文档语言相关的呈现方式都必需转换成对应的特异度为0的 CSS 规则,并插入用户代理样式表或网页作者样式表(如果是与HTML呈现方式有关的说明信息)的开始位置。

以下用户样式表会覆盖所有文档中 'b' 标签的字体粗细,以及所有XML文档中font标签通过color属性指定的颜色。它对HTML文档中font标签通过color属性指定的颜色没有影响。
b { font-weight: normal; }
font[color] { color: orange; }

以下例子会覆盖所有文档中font标签通过color属性指定的颜色:

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