6 分配属性值、层叠和继承

内容

注意:本规范的若干章节已被其他规范更新。请参阅最新 CSS Snapshot 中的 “层叠样式表 (CSS) — 官方定义”,其中列出了规范以及它们取代的章节。

CSS 工作组也在开发 CSS 2 级修订版 2(CSS 2.2)

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

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

属性的最终值是四步计算的结果:首先通过规范确定该值(“指定值”),然后解析为用于继承的值(“计算值”),如有必要再转换为绝对值(“使用值”),最后根据本地环境的限制进行转换(“实际值”)。

6.1.1 指定值

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

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

6.1.2 计算值

在层叠过程中,将指定值解析为计算值;例如,将 URI 转换为绝对形式,将 “em” 与 “ex” 单位计算为像素或绝对长度。计算值的过程从不要求用户代理渲染文档。

如果 UA 无法将 URI 解析为绝对 URI,则该 URI 的计算值就是其指定值。

属性的计算值按照属性定义中的 “Computed Value” 行规定确定。有关指定值为 “inherit” 时计算值的定义,请参见继承章节。

即使属性不适用于某个元素,只要该元素在“适用于”行中未被排除,计算值仍然存在。然而,某些属性可能会根据属性是否适用于该元素来决定其计算值。

6.1.3 使用值

计算值会在不进行文档格式化的情况下尽可能多地被处理。然而,有些值只能在布局文档时才能确定。例如,如果元素的宽度被设为其包含块宽度的某个百分比,就必须等到包含块的宽度确定后才能计算该宽度。使用值是指在计算值的基础上解析所有剩余依赖并得到的绝对值。

6.1.4 实际值

使用值原则上是用于渲染的值,但用户代理在特定环境下可能无法直接使用该值。例如,用户代理可能只能使用整数像素宽度来渲染边框,从而必须对计算宽度进行近似;又或者只能使用黑白两色而不能显示完整颜色。实际值就是在这些近似处理之后得到的使用值。

6.2 继承

正如前文所述,某些值会在文档树中被子元素继承。每个属性在定义时都会指明是否可继承。

假设有一个 H1 元素,其内部包含一个强调元素(EM)

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

如果没有为 EM 元素指定颜色,则该 EM 元素会继承父元素的颜色;因此如果 H1 的颜色是蓝色,EM 元素同样会显示为蓝色。

在继承发生时,子元素会继承计算值。父元素的计算值会同时成为子元素的指定值和计算值。

示例

例如,下面的样式表

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

以及该文档片段

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

则 H1 元素的 'font-size' 属性的计算值为 ‘13pt’(父元素 10pt 的 130%)。由于 'font-size' 的计算值是可继承的,EM 元素同样得到计算值 ‘13pt’。如果用户代理没有 13pt 的字体可用,则两者的'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(... )。

示例

以下两行等价,分别演示了使用 “url()” 与裸字符两种语法

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

为了让用户代理避免为不支持的媒体类型检索资源,作者可以指定媒体相关的@import规则。这些有条件导入在 URI 后使用逗号分隔的媒体类型列表。

示例

下面的规则展示了如何使 @import 规则依赖媒体类型

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

如果未声明任何媒体类型,则导入是无条件的。指定 ‘all’ 作为媒体等同于无条件导入。只有当目标媒体匹配媒体列表时,导入才会生效。

如果媒体列表中的某一项是目标媒体或 'all',则目标媒体匹配该媒体列表。

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

当同一样式表在文档中被多次导入或链接时,用户代理必须(或假装)将每个链接视为指向独立的样式表并进行处理。

6.4 层叠

样式表可以来源于三种不同的来源:作者、用户和用户代理。

这三种来源的样式表在作用范围上会重叠,它们的交互遵循层叠规则。

CSS层叠为每条样式规则分配权重。当多条规则同时适用时,权重最大的规则优先。

默认情况下,作者样式表的规则权重高于用户样式表的规则。但对于 “!important” 规则,这一优先级会被反转。所有用户和作者的规则都比 UA 的默认样式表规则权重更高。

6.4.1 层叠顺序

要寻找元素/属性组合的值,用户代理必须按下列顺序进行排序

  1. 找出所有适用于目标媒体类型的、对应元素和属性的声明。只要关联的选择器匹配该元素,并且目标媒体匹配所有 @media 规则中的媒体列表以及通过样式表路径的所有链接中的媒体列表,则该声明适用。
  2. 先按重要性(普通或 important)再按来源(author、user、user agent)排序。优先级从低到高如下
    1. 用户代理声明
    2. 用户普通声明
    3. 作者普通声明
    4. 作者 important 声明
    5. 用户 important 声明
  3. 对具有相同重要性和来源的规则,再按选择器特异性排序:特异性更高的选择器会覆盖特异性更低的选择器。伪元素和伪类分别计作普通元素和普通类。
  4. 最后按声明出现的顺序排序:如果两条声明的权重、来源和特异性完全相同,则后出现的获胜。来自导入样式表的声明视为位于本样式表自身的所有声明之前。

除个别声明的 “!important” 设置外,这一策略使作者样式表的权重高于阅读器的样式表。用户代理必须提供关闭特定作者样式表影响的功能,例如通过下拉菜单。符合 UAAG 1.0 检查点 4.14 即满足此条件[UAAG10]

6.4.2 !important 规则

CSS 试图在作者和用户样式表之间保持力量平衡。默认情况下,作者样式表的规则会覆盖用户样式表的规则(参见层叠规则 3)。

然而,为了保持平衡,带有 “!important” 标记的声明(在声明后紧跟 “!” 与关键字 “important”)会优先于普通声明。作者和用户样式表都可以包含 “!important” 声明,而用户的 “!important” 规则会覆盖作者的 “!important” 规则。此 CSS 特性通过让有特殊需求的用户(如大字号、特定配色等)控制呈现,提高了文档的可访问性。

简写属性(例如'background')标记为 “!important” 等价于将其所有子属性全部标记为 “!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 计算选择器的特异性

选择器的特异性计算如下

特异性仅依据选择器的形式计算。特别是形如 “[id=p33]” 的选择器被视为属性选择器(a=0, b=0, c=1, d=0),即使该 id 属性在源文档的 DTD 中被声明为 “ID”。

将四个数 a‑b‑c‑d(在基数较大的数制中)连接起来即得到特异性。

示例

一些示例

 *             {}  /* 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 元素中的声明。

6.4.4 非 CSS 表现提示的优先级

UA 可以选择尊重 HTML 源文档中的表现属性。如果选择如此,这些属性会被转换为对应的 CSS 规则,特异性为 0,并且被视为插入在作者样式表的最前面。因此后续的样式表规则可以覆盖它们。在过渡阶段,这一策略有助于表现属性与样式表共存。

对于 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 的表现提示一样,作为特异性为零、放置在作者样式表开头的作者层级规则。

示例

下面的用户样式表会覆盖所有文档中 元素的字体粗细,以及 XML 文档中带有 color 属性的 元素的颜色,但不会影响 HTML 文档中带有 color 属性的 元素的颜色。

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

然而,下面的样式表会覆盖所有文档中 元素的颜色。

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