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

内容

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

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

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

6.1.1 指定值

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

  1. 如果层叠结果得出一个值,则使用该值。除了如果值是 'inherit',则指定值在下面的“'inherit'值”中定义。
  2. 否则,如果属性是继承的并且元素不是文档树的根元素,则使用父元素的计算值。
  3. 否则,使用属性的初始值。每个属性的初始值在属性的定义中有所指示。

6.1.2 计算值

在层叠过程中,指定值解析为计算值;例如,将URI解析为绝对URI,'em' 和 'ex' 单位计算为像素或绝对长度。计算值不要求用户代理渲染文档。

对于用户代理无法解析为绝对URI的URI,其计算值为指定值。

属性的计算值是根据属性定义中的计算值行来确定的。有关在指定值为 'inherit' 时计算值的定义,请参阅继承部分。

即使属性不适用,计算值仍然存在,如'适用于'行所定义。然而,一些属性可能定义了当属性适用于某个元素时该元素的属性计算值。

6.1.3 使用值

计算值尽可能在不格式化文档的情况下进行处理。然而,一些值只能在布局文档时确定。例如,如果某个元素的宽度设置为其包含块宽度的某个百分比,则在确定包含块的宽度之前,无法确定该元素的宽度。使用值是通过将计算值进行任何剩余依赖关系解析为绝对值的结果。

6.1.4 实际值

使用值原则上是用于渲染的值,但用户代理可能无法在给定的环境中使用该值。例如,用户代理可能只能渲染具有整数像素宽度的边框,因此可能需要近似计算宽度,或者用户代理可能被迫仅使用黑白色调而不是全彩色。实际值是应用任何近似计算后的使用值。

6.2 继承

如上所述,某些值会被文档树中某个元素的子元素继承。每个属性都定义它是否会被继承。

假设有一个包含强调元素(EM)的H1元素:

<H1>标题<EM>很</EM>重要!</H1>

如果EM元素没有指定颜色,强调的“很”将继承父元素的颜色,因此如果H1的颜色是蓝色,EM元素也将显示为蓝色。

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

Example(s):

例如,给定以下样式表:

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

以及以下文档片段:

<BODY>
  <H1>一个<EM>大的</EM>标题</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' 值,则该属性将分配其初始值。

Example(s):

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

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

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

6.3 @import规则

'@import' 规则允许用户从其他样式表中导入样式规则。在CSS 2.2中,任何@import规则必须在所有其他规则之前(如果存在@charset规则,则在其之后)。有关用户代理何时必须忽略@import规则的详细信息,请参阅 解析 部分。'@import' 关键字后必须跟随要包含的样式表的URI。也允许使用字符串;它将被解释为带有url(...)的内容。

Example(s):

以下几行在含义上是等效的,展示了'@import'语法的两种形式(一种带有 "url()",另一种带有裸字符串):

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

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

Example(s):

以下规则说明了如何使@import规则依赖于媒体:

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

在没有指定任何媒体类型的情况下,导入是无条件的。为媒体指定'all'的效果相同。只有当目标媒体与媒体列表匹配时,导入才生效。

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

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

当在多个地方导入或链接到同一个样式表时,用户代理必须处理每个链接(或表现得像它们那样)就像链接到一个单独的样式表一样。

6.4 级联

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

来自这三种来源的样式表将在作用范围上重叠,并且它们将根据级联进行交互。

CSS 级联 为每个样式规则分配一个权重。当多个规则适用时,权重最大的规则优先。

默认情况下,作者样式表中的规则比用户样式表中的规则具有更大的权重。然而,对于 "!important" 规则,优先级顺序是相反的。所有用户和作者规则都比用户代理的默认样式表中的规则具有更大的权重。

6.4.1 级联顺序

为了找到元素/属性组合的值,用户代理必须应用以下排序顺序:

  1. 找到所有适用于目标媒体类型中该元素和属性的声明。如果相关选择器与该元素匹配,并且目标媒体与包含声明的所有 @media 规则上的媒体列表匹配,且样式表的访问路径上的所有链接都匹配,则声明适用。
  2. 根据重要性(普通或重要)和来源(作者、用户或用户代理)排序。按优先级升序排列:
    1. 用户代理声明
    2. 用户普通声明
    3. 作者普通声明
    4. 作者重要声明
    5. 用户重要声明
  3. 按选择器的特异性对具有相同重要性和来源的规则进行排序:更具体的选择器将覆盖更一般的选择器。伪元素和伪类分别被视为普通元素和类。
  4. 最后,按指定顺序排序:如果两个声明具有相同的权重、来源和特异性,则后者胜出。导入样式表中的声明被视为在样式表本身中的声明之前。

除了对个别声明设置 "!important" 外,这种策略赋予作者的样式表比读者的样式表更高的权重。用户代理必须让用户能够关闭特定作者样式表的影响,例如通过下拉菜单。符合UAAG 1.0 检查点 4.14 的条件 [UAAG10]

6.4.2 !important 规则

CSS 试图在作者和用户样式表之间创建一种权力平衡。默认情况下,作者样式表中的规则会覆盖用户样式表中的规则(参见级联规则3)。

然而,为了保持平衡,"important"声明(声明后跟随分隔符标记"!"和关键词"important")优先于普通声明。作者和用户样式表都可以包含"important"声明,并且用户的"important"规则会覆盖作者的"important"规则。这个 CSS 特性通过赋予有特殊需求的用户(如大字体、颜色组合等)对展示的控制权,提高了文档的可访问性。

声明一个简写属性(例如,"background")为"important",相当于将其所有子属性声明为"important"。

Example(s):

在以下示例中,用户样式表中的第一个规则包含一个"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 }

6.4.3 计算选择器的特异性

选择器的特异性计算如下:

特异性仅基于选择器的形式进行计算。特别地,形如 "[id=p33]" 的选择器被视为属性选择器(a=0, b=0, c=1, d=0),即使 id 属性在源文档的 DTD 中被定义为 "ID"。

将四个数字 a-b-c-d 连接在一起(在一个具有大基数的数字系统中)即得出特异性。

Example(s):

一些示例:

 *             {}  /* a=0 b=0 c=0 d=0 -> 特异性 = 0,0,0,0 */
 li            {}  /* a=0 b=0 c=0 d=1 -> 特异性 = 0,0,0,1 */
 li:first-line {}  /* a=0 b=0 c=0 d=2 -> 特异性 = 0,0,0,2 */
 ul li         {}  /* a=0 b=0 c=0 d=2 -> 特异性 = 0,0,0,2 */
 ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> 特异性 = 0,0,0,3 */
 h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> 特异性 = 0,0,1,1 */
 ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> 特异性 = 0,0,1,3 */
 li.red.level  {}  /* a=0 b=0 c=2 d=1 -> 特异性 = 0,0,2,1 */
 #x34y         {}  /* a=0 b=1 c=0 d=0 -> 特异性 = 0,1,0,0 */
 style=""          /* a=1 b=0 c=0 d=0 -> 特异性 = 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 元素中的声明。

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 并且要么进入 UA 级别的级联,要么像 HTML 的表现性提示一样,作为特异性为零的作者级规则,放置在作者样式表的开始处。

Example(s):

以下用户样式表将覆盖所有文档中 'b' 元素的字体粗细,以及 XML 文档中带有 color 属性的 'font' 元素的颜色。它不会影响带有 color 属性的 HTML 文档中的任何 'font' 元素的颜色:

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

然而,以下内容将覆盖所有文档中 'font' 元素的颜色:

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