层叠样式表第2级 CSS2规范开发手册 - WEB前端开发 专注前端开发,关注用户体验

6 指定属性值,层叠和继承

    目录

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

    一旦用户端解析了一个文档并且生成了文档树,它必须为文档树中的每一个元素,根据目标媒介类型所适用的每一个属性,指定一个值。

    一个属性的最终的值的得到需要经过三步计算:首先通过规定确定值(“指定值”),然后在需要的情况下转换成一个绝对的值(“计算值”),并根据当时的环境最终转换(“实际值”)。

6.1.1 指定值

    用户必须先基于如下的机制(以优先级排序)来为一个属性分配一个指定值:

  1. 如果值中包含层叠,使用层叠。
  2. 否则,如果属性是继承的,使用它父元素的值,通常是父元素的计算值。
  3. 否则,使用属性的初始值。每一个属性的初始值出现在属性的定义中。

    由于文档树的根元素没有父元素,因此不能使用来自父元素的值。在这种情况下,如果有必要,可以使用初始值。

6.1.2 计算值

    指定值可以是绝对的(即它们不是相对于另外一个值的指定值,如'red'或'2mm')或者是相对的(即它们是相对于另外一个值的指定值,如'auto','2em'及'12%')。对于绝对值,不需要经过计算来得到计算值。

    另一方面,相对值必须转换为计算值:百分比要乘以一个参考值(每一个属性都会定义参考值是什么),包含相对单位的值(em,ex,px)必须乘以相应的字体或点的尺寸以得到绝对值,'auto'值必须由各属性给出的公式加以计算,某些关键字('smaller','bolder','inherit')根据它们的定义而加以替换。

    大部分情形下,元素继承计算值。不过有一些属性的指定值也可以被继承(例如'line-height'属性的数字值)。子元素不继承计算值的情况在属性定义中有描述。

6.1.3 实际值

    原则上说,计算值已经可以使用,不过用户端在特定的环境中可能无法使用这些值。例如,用户端可能只能渲染整数点宽的边框,因此可能对计算的宽度加以近似。实际值就是经过近似之后的计算值。

6.2 继承

    文档树中一元素的某些值可以被其子元素继承。每一个属性定义了它能否被继承。

    假定在一个H1元素内有一个着重元素(EM):

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

    如果对于EM元素没有指定颜色,则着重的"is"将继承父元素的颜色。因此,如果H1的颜色是蓝色,EM元素也是蓝色。

    要设置文档的“缺省”样式属性,作者可以在文档树的根上设置属性。例如,在HTML中,HTML或BODY元素可以实现这一功能。这一方法即使在作者省略HTML中的BODY标记时,仍然可行,因为HTML解析器会补足缺掉的标记。

例子:

    比方说,由于'color'属性是可继承的,所有BODY元素的后代都继承颜色值为'black':

BODY { color: black; }

    指定的百分比值不被继承,但是计算值可以被继承。

例子:

    例如,在下面的样式表:

BODY { font-size: 10pt }
H1 { font-size: 120% }

    和文档片段中:

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

    H1元素的'font-size'属性的计算值为'12pt'(其父元素值10pt的120%)。由于'font-size'的计算值被继承,EM元素也继承'12pt'的计算值。如果用户端没有12pt的字体,则H1和EM元素'font-size'的实际值可能是,比方说,'11pt'。

6.2.1 'inherit'

    每一个属性可以有一个指定值为'inherit',即,对于给定的元素,该属性和它父元素相对属性的计算值取一样的值。继承值通常只用作后备值,它可以通过显式地设置'inherit'而得到加强。

例子:

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

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

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

6.3 @import规则

    '@import'规则允许用户从其它样式表中引入样式规则。任何@import规则必须出现在样式表中所有规则之前。'@import'关键字必须跟随一个要包含的样式表的URI。也允许字符串,这时它将被解释为它包含在url(...)内。

例子:

    下面这几行含义是一样的,演示了两种'@import'语法(一个带有"url()",而另一个是字符串):

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

    为了使用户端避免引入不被支持的媒介类型的资源,作者可以指定媒介相关的@import规则。这些条件引入在URI之后指定了一个以逗号分割的媒介类型列表。

例子:

    下面的规则对于同样的媒介的效果和假定引入的样式表包含在一个@media规则内是一样的,只是它可能使UA省掉无效下载的过程和时间。

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

    如果没有指明任何媒介类型,则引入使无条件的。将媒介指定为'all'效果一样。

6.4 层叠

    样式表可能有三个不同的来源:作者,用户和用户端。

    这三个来源来的样式表可能在范围上有重叠。它们根据层叠规则互相作用。

    CSS的层叠对每一个样式规则指定一个权重。如果要应用若干个规则,那么权重最大的那个规则具有优先权。

    缺省时,作者的样式表规则较用户样式表规则优先级高。不过,对于"!important"规则,保留其优先级。所有的用户和作者的规则的权重都比UA缺省样式表中的规则的权重大。

    引入的规则同样层叠,它们的权重取决于它们引入的顺序。定义在一个给定的样式表中的规则超越从其它样式表中引入的规则。类似的,引入的规则本身可以引入并超越其它样式表,优先级规则同样适用。

6.4.1 层叠顺序

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

  1. 对于目标媒介类型,找到存在疑问的元素和属性的所有声明。如果相关联的选择子匹配存在疑问的元素,则声明适用。
  2. 声明的原始排序根据权重和来源:对于一般的声明,作者样式表超越用户样式表,用户样式表超越缺省样式表。对于"!important"声明,用户样式表超越作者样式表,作者样式表超越缺省样式表。引入的样式表和引入它的样式表具有相同的来源。
  3. 声明的第二排序基于选择子的特殊性:特殊的选择子超越一般的选择子。伪元素和伪类分别被视为一般元素和一般类。
  4. 最后,根据先后次序来排列:如果两条规则具有相同的权重,相同的来源和相同的特殊性,则后出现的规则超越先出现的规则。引入的样式表中的规则被认为出现在样式表本身的所有规则之前。

    除了个别声明的"!important"设置,上述策略给予作者的样式表比用户样式表更大的权重。因此用户端允许用户通过一个下拉菜单而关闭某一样式表的影响就很重要。

6.4.2 !important规则

    CSS试图在作者样式表和用户样式表的权力之间创建一个平和。缺省情况下,作者样式表的规则超越用户样式表的规则(见层叠规则3)。

    不过,为了平衡,一个"!important"声明(关键字"!"和"important"出现在声明之后)将比一个一般的声明更具有优先级。作者和用户的样式表都可以包含"!important"声明, 并且用户的"!important"规则超越作者的"!important"规则。这一CSS特性使用户对于呈现可以进行特殊要求的控制(如更大的字体,颜色组合等),从而改进了文档的可读性。

     注意!这是自CSS1来的语义的变化。在CSS1中,作者的"!important"规则超越用户的"!important"规则。

    将一个缩写属性(如'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: 12pt sans-serif !important }
P { font-size: 24pt }

6.4.3 选择子特殊性的计算

    一个选择子的特殊性是这样计算的:

    将三个数字相连(数字进制要以大的为准),得到特殊性。

例子:

    一些例子:

*             {}  /* a=0 b=0 c=0 -> specificity =   0 */
LI            {}  /* a=0 b=0 c=1 -> specificity =   1 */
UL LI         {}  /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI      {}  /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]{}  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red  {}  /* a=0 b=1 c=3 -> specificity =  13 */ 
LI.red.level  {}  /* a=0 b=2 c=1 -> specificity =  21 */
#x34y         {}  /* a=1 b=0 c=0 -> specificity = 100 */ 

    HTML中,一个元素的“style”属性的值是样式表规则。这些规则没有选择子,不过为了层叠算法第三步的要求,它们被认为具有一个ID选择子(特殊性:a=1,b=0,c=0)。考虑到第四步的要求,它们被认为是在其它所有规则之后。

    

<HEAD>
<STYLE type="text/css">
  #x97z { color: blue }
</STYLE>
</HEAD>
<BODY>
<P ID=x97z style="color: red">
</BODY>

    上面这个例子中,P元素的颜色是红色的。虽然两个声明的特殊性是一样的,但是由于层叠规则4,"style"属性中的声明将超越STYLE元素中的声明。

6.4.4 非CSS呈现提示的优先性

    用户端可能给予那些不是来自样式表的呈现提示以优先考虑,例如HTML中的FONT元素或"align"属性。如果是这样,这些非CSS呈现提示必须被转换到相应的CSS规则,且其特殊性为零。这些规则被认为是写在作者样式表的开头,并且可能被后续的样式表规则超越。

    注意。在转换时期,这一策略使得样式属性和样式表的共存更加容易。

    注意。在CSS1中,非CSS呈现提示的特殊性为1,而不是0。这一改变是因为CSS2引入了全局选择子,而它的特殊性为0。