Skip to content

CSS 属性计算过程

我们所书写的任何一个 HTML 元素,实际上都有完整的一整套 CSS 样式

这个可以从这边 chrome 控制台 element 随便选中一个元素 标签右边点击 computed

选中 show all 可以看到所有的计算好的属性

元素的所有属性
这张图片害羞了
元素的所有属性

所以就是 我们所书写的任何一个 HTML 元素,实际上都有完整的一整套 CSS 样式

属性的计算过程

既然有这么多属性 这些属性怎么出来的 如下

这边先上个代码例子

html
<div>
  <h1>这是个H1</h1>
  <p style="color:red">这是个段落</p>
</div>

确定声明值

首先第一步,是确定声明值.所谓声明值就是作者自己所书写的 CSS 样式.

这里我们声明了 p 元素为红色,那么就会应用此属性设置. 当然,除了作者样式表,一般浏览器还会存在“用户代理样式表”,简单来讲就是浏览器内置了一套样式表.

内置样式
这张图片害羞了
内置样式

在上面的示例中,作者样式表中设置了 color 属性,而用户代理样式表(浏览器提供的样式表)中设置了诸如 display、margin-block-start、margin-block-end、margin-inline-start、margin-inline-end 等属性对应的值. 这些值目前来讲也没有什么冲突,因此最终就会应用这些属性值.

层叠冲突

在确定声明值时,可能出现一种情况,那就是声明的样式规则发生了冲突. 此时会进入解决层叠冲突的流程.而这一步又可以细分为下面这三个步骤: 比较源的重要性比较优先级比较次序 来来来,我们一步一步来看.

比较源的重要性

当不同的 CSS 样式来源拥有相同的声明时,此时就会根据样式表来源的重要性来确定应用哪一条样式规则. 那么问题来了,咱们的样式表的源究竟有几种呢?

整体来讲有三种来源:
浏览器会有一个基本的样式表来给任何网页设置默认样式.这些样式统称用户代理样式.
网页的作者可以定义文档的样式,这是最常见的样式表,称之为页面作者样式.
浏览器的用户,可以使用自定义样式表定制使用体验,称之为用户样式. 对应的重要性顺序依次为:页面作者样式 > 用户样式 > 用户代理样式
更详细的来源重要性比较,可以参阅 MDN Cascade
我们来看一个示例. 例如现在有页面作者样式表用户代理样式表中存在属性的冲突,那么会以作者样式表优先.

作者样式表
这张图片害羞了
作者样式表

可以明显的看到,作者样式表用户代理样式表中同时存在的 display 属性的设置,最终作者样式表干掉了用户代理样式表中冲突的属性.
这就是第一步,根据不同源的重要性来决定应用哪一个源的样式.

比较优先级

那么接下来,如果是在在同一个源中有样式声明冲突怎么办呢?此时就会进行样式声明的优先级比较.

在上面的代码中,同属于页面作者样式,源的重要性是相同的,此时会以选择器的权重来比较重要性. 很明显,上面的选择器的权重要大于下面的选择器,因此最终标题呈现为 50px .

比较优先级
这张图片害羞了
比较优先级

可以看到,落败的作者样式在 Elements>Styles 中会被划掉. 有关选择器权重的计算方式,不清楚的同学,可以进入此传送门:MDN Specificity

比较次序

经历了上面两个步骤,大多数的样式声明能够被确定下来.但是还剩下最后一种情况,那就是样式声明既是同源,权重也相同. 此时就会进入第三个步骤,比较样式声明的次序.

这里的代码中,同样都是页面作者样式选择器的权重也相同,此时位于下面的样式声明会层叠掉上面的那一条样式声明,最终会应用 40px 这一条属性值.

比较次序
这张图片害羞了
比较次序

至此,样式声明中存在冲突的所有情况,就全部被解决了.

使用继承

层叠冲突这一步完成后,解决了相同元素被声明了多条样式规则究竟应用哪一条样式规则的问题. 那么如果没有声明的属性呢?此时就使用默认值么? No、No、No,别急,此时还有第三个步骤,那就是使用继承而来的值.

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

属性继承
这张图片害羞了
属性继承

这里有两个点需要注意一下. 首先第一个是我强调了是 最近的 div 元素,看下面的例子:

最近的
这张图片害羞了
最近的

因为这里并不涉及到选中 p 元素声明 color 值,而是从父元素上面继承到 color 对应的值,因此这里是 谁近就听谁 的,初学者往往会产生混淆,又去比较权重,但是这里根本不会涉及到权重比较,因为压根儿就没有选中到 p 元素. 第二个就是哪些属性能够继承? 关于这一点的话,大家可以在 MDN 上面很轻松的查阅到.例如我们以 text-align 为例,如下图所示:

是不是继承的
这张图片害羞了
是不是继承的

使用默认值

好了,目前走到这一步,如果属性值都还不能确定下来,那么就只能是使用默认值了.

前面我们也说过,一个 HTML 元素要在浏览器中渲染出来,必须具备所有的 CSS 属性值,但是绝大部分我们是不会去设置的,用户代理样式表里面也不会去设置,也无法从继承拿到,因此最终都是用默认值. 好了,这就是关于 CSS 属性计算过程的所有知识了.

一道面试题

好了,学习了今天的内容,让我来用一道面试题测试测试大家的理解程度. 下面的代码,最终渲染出来的效果,a 元素是什么颜色?p 元素又是什么颜色?

html
<style>
  .test {
    color: skyblue;
  }
</style>

<body>
  <div class="test">
    <a href="baidu.com">这是个A</a>
    <p>这是个P</p>
  </div>
</body>

大家能说出为什么会呈现这样的结果么?

解答如下:

答案
这张图片害羞了
答案

答案解释

实际上原因很简单,因为 a 元素在用户代理样式表中已经设置了 color 属性对应的值,因此会应用此声明值.而在 p 元素中无论是作者样式表还是用户代理样式表,都没有对此属性进行声明,然而由于 color 属性是可以继承的,因此最终 p 元素的 color 属性值通过继承来自于父元素. 你答对了么?-)