CSS 属性计算过程

总的来讲,属性值的计算过程,分为如下这么 4 个步骤:

  1. 确定声明值
  2. 层叠冲突
  3. 使用继承
  4. 使用默认值

MDN: 层叠、优先级与继承

确定声明值

所谓声明值就是作者自己所书写的 CSS 样式, 例如:

1
2
3
p {
color: red;
}

这里我们声明了 p 元素为红色,那么就会应用此属性设置。

当然,除了作者样式表,一般浏览器还会存在 用户代理样式表 User agent Stylesheet (即浏览器默认的样式表), 简单来讲就是浏览器 内置 了一套样式表。

![元素样式](E:_Project_git仓库\ImageHost\ImageHost\CSS 属性计算过程\2022-08-13-063500.png)

在图中,作者样式表中设置了 color 属性,而用户代理样式表中设置了像这些值:

1
2
3
4
5
6
7
{
display
margin-block-start
margin-block-end
margin-inline-start
margin-inline-end
}

这些值目前来讲也没有什么冲突,因此最终就会应用这些属性值。

层叠冲突

在确定声明值时,可能出现一种情况,那就是声明的样式规则发生了冲突。

此时会进入解决层叠冲突的流程。而这一步又可以细分为下面这三个步骤:

  • 比较源的重要性
    • 比较优先级
      • 比较次序

比较源的重要性

整体来讲有三种来源:

  • 浏览器会有一个基本的样式表来给任何网页设置默认样式。这些样式统称 用户代理样式
  • 网页的作者可以定义文档的样式,这是最常见的样式表,称之为 页面作者样式
  • 浏览器的用户,可以使用自定义样式表定制使用体验,称之为 用户样式

对应的重要性顺序依次为:页面作者样式 > 用户样式 > 用户代理样式

更详细的来源重要性比较,可以参阅 MDNCSS 层叠样式表 CSS层叠

来源 重要程度
1 用户代理 普通
2 用户 普通
3 页面作者 普通
4 CSS 动画 见下节
5 页面作者 !important
6 用户 !important
7 用户代理 !important
8 css 过渡 (css transitions)

比较优先级

源的重要性是相同的,此时会以 选择器的权重 来比较重要性

1
2
3
4
5
6
7
.test h1{
font-size: 50px;
}

h1 {
font-size: 20px;
}

很明显,上面的选择器的权重要大于下面的选择器,因此最终标题呈现为 50px

在浏览器中可以看到,落败的作者样式在 Elements>Styles 中会被划掉。

关于选择器的权重计算方式,可以查阅 MDNCSS:层叠样式表 - 优先级

选择器类型 例子
1 类型选择器 h1
伪元素 ::before
2 类选择器 .example
属性选择器 [type="radio"]
伪类 :hover
3 ID 选择器 #example

注意:以下的选择器对优先级 没有 影响

比较次序

这一步判断和确定的是,样式声明既是同源,权重也相同的情况下, 比较样式声明的次序

1
2
3
4
5
6
7
h1 {
font-size: 50px;
}

h1 {
font-size: 20px;
}

此时位于下面的样式声明会层叠掉上面的那一条样式声明,最终会应用 20px 这一条属性值

使用继承

层叠冲突这一步完成后,解决了相同元素被声明了多条样式规则究竟应用哪一条样式规则的问题。

那么没有声明的属性呢?此时还有第三个步骤,那就是使用继承而来的值。

1
2
3
<div>
<p>Lorem ipsum dolor sit amet.</p>
</div>
1
2
3
div {
color: red;
}

在上面的代码中,我们针对 div 设置了 color 属性值为红色,而针对 p 元素我们没有声明任何的属性
但是由于 color 是可以继承的,因此 p 元素从最近的 div 身上继承到了 color 属性的值

有两点需要注意,一个是属性可以继承,一个是最近的元素:

  1. 最近的元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <div class="test">
    <div>
    <p>Lorem ipsum dolor sit amet.</p>
    </div>
    </div>

    <style>
    div {
    color: red;
    }
    .test{
    color: blue;
    }
    </style>

    因为这里并不涉及到选中 p 元素声明 color 值,而是从父元素上面继承到 color 对应的值,因此这里是 谁近就听谁
    这里根本不会涉及到权重比较,因为压根儿就没有选中到 p 元素

  2. 哪些属性能够继承

    可以通过 MDN 查看,比如 color > 形式定义 > 是否是继承属性

使用默认值

如果上述步骤都还未确定属性值,那就只能使用默认值了

一个 HTML 元素要在浏览器中渲染出来,必须具备所有的 CSS 属性值

但是绝大部分我们是不会去设置的,用户代理样式表 里面也不会去设置,也无法从继承拿到

因此最终都是用默认值