CSS之样式属性值及其层叠与继承关系

CSS之样式属性值及其层叠与继承关系

本篇介绍CSS样式规则的层叠与继承关系,并介绍用户代理如何计算和使用样式属性值布局并渲染文档。

属性值

当用户代理将一个文档解析生成文档树时,它必须为文档树中的每一个元素在目标媒体中使用的每一个样式属性分配一个值。

一个样式属性的最终值通过四步计算得出:

  • 1.声明值(specified value):该值由CSS样式属声明计算得出;
  • 2.计算值(computed value):该值是解析定义值生成,用于样式属性继承;
  • 3.使用值(used value):转换成一个绝对值;
  • 4.实际值(actual value):根据实际环境的限制,最后得到属性实际使用值。

声明值(Specified value)

用户代理按照如下优先级机制为每一个属性分配声明值:

  • 1.如果根据层叠样式得出某属性的一个特定值,则该值为声明值;
  • 2.否则,若该属性可继承且当前元素不是文档树根元素,则使用当前元素父元素上同名属性的计算值作为声明值;
  • 3.否则,使用该属性的初始值(initial value),初始值在该属性标准定义中规定声明。

计算值(Coputed value)

在样式层叠过程中,某些样式定义值会被解析成计算值,比如em和rem等相对单位会被解析成对应得px值。解析计算值时,不需要用户代理渲染文档。

属性的计算值取决于该属性的定义值,比如之前使用em或rem,其计算方式不同;若某属性声明值为关键字inherit,计算值是比较特殊的,下文会做详细介绍。

使用值(Actual value)

用户代理在尚未格式化文档时就尽可能早的得到计算值,然而,一些属性值只有文档布局完成才能决定,如width属性,当width值设为百分比时,其计算值是相对于元素包含块宽度的,只有包含块宽度确定了,元素width值才能确定,所以,使用值就是根据剩余依赖将计算值转换成绝对结果值。

实际值(Actual value)

使用值主要是用于渲染文档,但是在某些环境,用户代理可能不能使用给定值,如,用户代理可能不能渲染出浮点数像素宽度的边框或某些字体,这个时候,用户代理会进行近似处理(approximate),比如对宽度取整或使用默认字体替换当前不可用字体,实际值就是使用值经过近似处理后得到的值。

实例

如下html结构:


<p>我是p段落内容,字体大小为19px</p>

其样式如下:


html, body {font-size: 16px;} p {font-size: 1.2rem;}

以上代码中,p段落内容的font-size属性声明值为1.2rem,计算值为为19.2px(16px * 1.2 = 19.2px),其使用值也为19.2px,但是其实际值为19px。

继承(Inheritance)

在文档树中,元素的某些样式属性值可以被其子元素继承,这个继承关系在样式属性定义文档中有说明。

如:


<p>我是p段落内容,字体大小为19px<span>我是span内容,我的字体大小继承自p段落</span></p>

继承值

当子元素继承其父元素某属性时,当前元素属性值是继承自父元素该属性的计算值,这个值既是当前元素的声明值,又是计算值。

如下:


<p>我是p段落内容,字体大小为19px<span>我是span内容,我的字体大小继承自p段落</span></p>

html, body {font-size: 16px;} p {font-size: 1.2rem;}

p段落内容的font-size属性声明值为1.2rem,计算值为为19.2px(16px * 1.2 = 19.2px),而span元素font-size属性继承自父元素p的font-size属性的计算值,即19.2px,其声明值和计算值都是是19.2px,但是其实际值为19px。

inherit关键字

每个属性有一个inherit层叠值,也就是说,一个元素的某属性值和其父元素该属性的声明值相同,inherit关键字值可以强制属性值继承自父元素。

若在根元素上,设置某属性值为inherit,则根元素该属性值为属性初始值。

@import规则

这个规则,我们通常很少用,但是我们也有必要了解它。@import允许用户在样式表中引入其他样式表,在样式表中,@import规则必须放在其他除@charset规则之外的所有样式规则前面。

@import关键字后面紧跟一个URI字符串或者url()构造的URI字符串,如下,两条规则等价:


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

在URL后面还可以可选的声明媒体类型依赖参数(多个值以逗号分隔), 默认是等同于关键字all,即适用于所有媒体类型:


@import url("mystyle.css") all; @import url("mystyle.css") print; @import url("mystyle.css") tv, projection;

若某一样式表在同一文档中多次@import引入,用户代理将对其进行多次加载处理。

层叠(cascade)

样式表来源可以分为三类:所有者(author),用户(user),用户代理(user agent,主要是浏览器)。

  • 1.所有者:所有者通过文档语言的规则定义样式表,如,HTML中,样式表可以内联或者外链。
  • 2.用户:用户可以为文档定义样式信息,如,用户可以定义一个包含样式表的文件,链接到文档;用户代理可以提供特定用户界面产生一个用户样式表。
  • 3.用户代理:用户代理会提供默认样式表,它定义在没有提供其他样式表时,如何渲染文档。如,<em>元素默认就是斜体。

以上三种来源的样式表在同一作用域(同一文档)内会发生交叠,他们根据层叠规则决定最后适用的样式。

CSS层叠为每一条样式规则分配一个权重,当出现多条相同规则时,权重高的优先。

默认地,所有者样式表比用户样式表权重高,用户代理样式表权重最低,但,使用!important规则会强制提升样式规则权重,详见下一节-层叠顺序。

层叠顺序

用户代理根据以下排序规则,决定最终适用于某元素的样式规则:

  • 1.首先获取所有匹配此元素声明的样式规则(包括匹配当前媒体类型和选择器匹配当前元素)。
  • 2.根据重要性以及样式来源进行排序,优先级(权重)由低到高依次为:
    • 1.用户代理声明样式
    • 2.用户样式表普通声明
    • 3.所有者样式表普通声明
    • 4.所有者样式表!important声明
    • 5.用户样式表!important声明
  • 3.对于相同重要性和来源的样式规则按如下规则进行排序:
    • 1.使用特定选择器的样式规则,其优先级(权重)高于使用通用选择器的样式规则
    • 2.伪类和伪元素选择器当作普通类和元素选择器
  • 4.按声明顺序排序:对于多条权重相同,来源相同的样式规则,后面的覆盖前面的,@import引入的样式规则总是在当前样式表所有样式规则的前面。

选择器优先级

选择器的优先级计算方式如下,使用a, b, c , d累计分数,abcd值越大,优先级越高,该选择器下声明的样式属性值覆盖其他值:

  • 1.a, 通过style属性声明的行内样式规则,a = 1;否则a = 0
  • 2.b, 其值为选择器中元素ID的次数
  • 3.c, 其值为选择器中其他属性和伪类出现的次数
  • 4.d, 其值为选择器中元素和伪元素名出现的次数

* {} /* a=0,b=0,c=0,d=0 => 0000 */ div {} /* a=0,b=0,c=0,d=1 => 0001 */ div:last-child {} /* a=0,b=0,c=0,d=2 => 0002 */ div p {} /* a=0,b=0,c=0,d=2 => 0002 */ h1 p[data-index] {} /* a=0,b=0,c=1,d=2 => 0012 */ h1 p.para {} /* a=0,b=0,c=1,d=2 => 0012 */ h1 p.para.red {} /* a=0,b=0,c=2,d=2 => 0022 */ #login {} /* a=0,b=1,c=0,d=0 => 0100 */ style="" /* a=1,b=0,c=0,d=0 => 1000 */

如下代码:


<style> p#para { color: red; } </style>

html结构:


<p id="para" style="color:blue;">我的字体蓝色</p>

原创文章,转载请注明: 转载自 熊建刚的博客

本文链接地址: CSS之样式属性值及其层叠与继承关系

熊 建刚

热爱前端,但不局限于前端,喜欢尝试各种新技术,爱好读书。

发表评论

电子邮件地址不会被公开。 必填项已用*标注