web前端渡一大师课 CSS属性计算过程
你是否了解CSS 的属性计算过程呢?
<body>
<h1>这是一个h1标题</h1></body>
目前我们没有设置改h1的任何样式,但是却能看到改h1有一定的默认样式,例如有默认的字体大小,默认的颜色
那么问题来了,我们这个h1元素上面除了有默认字体大小,默认颜色等属性以外,酒精还有哪些属性呢?
答案: 是该元素上面会有CSS所有的属性,你可以打开浏览器的开发者面板,选择[元素],切换到[计算样式],之后勾选[全部显示],此时你就能看到在次h1上面所有css属性对应的值
换句话说,我们所书写的任何一个HTML元素,实际上都有完整的一整套CSS样式,这一点往往是让初学者比较意外的,因为我们平时在书写CSS样式时,往往只会书写必要的部分,例如前面的:
p{
color : red
}
这往往会给我们造成一种错觉,认为该p元素上面就只有color属性,而真是的情况确实是,任何一个HTML,都有一套完整的CSS样式,只不过你没有书写的样式,大概率可能会使用其默认值,例如上图中h1一个样式都没有设置,全部都用的默认值.
但是注意,我这里强调的是"大概率可能",难道还有我们"没有设置值,但是不使用默认值"的情况么?
嗯,确实有的,所以我才强调你要了解"CSS属性的计算过程"
总的来讲,属性值的计算过程,分为如下这么4个步骤:
- 确定声明值
- 层叠冲突
- 使用继承
- 使用默认值
1. 确定声明值
首先第一步,是确定声明值,所谓声明值就是作者自己所书写的CSS样式,例如前面的:
p{
color: red;
}
这里我们声明了p元素为红色,那么就会应用此属性设置
当然,除了作者样式表,一般浏览器还会存在"用户代理样式表",简单来说就是浏览器内置了一套样式表.
在上面的示例中,作者样式表中设置了color属性,而用户代理样式表(浏览器提供的样式表)中设置了诸如display,margin-block-start,margin-block-end,margin-inline-start,margin-inline-end 等属性对应的值.
这些值目前来讲也没有什么冲突,因此最终就会应用这些属性值
2.层叠冲突
在确定声明值时,可能出现一种情况,那就是声明的样式规则发生了冲突.
此时会进入解决层叠冲突的流程,而这一步又可以细分为下面这三个步骤:
- 比较源的重要性
- 比较优先级
- 比较次序
1.比较源的重要性
当不同的CSS样式来源有用相同的声明时,此时就会根据样式表来源的重要性来确定应用哪一条样式规则.
那么问题来了,咱们的样式表的源究竟有几种呢?
整体来讲有三种来源:
- 浏览器会有一个基本的样式表来给任何网页设置默认样式,这些样式统称为用户代理样式.
- 网页的作者可以定义文档的样式,这是最常见的样式表,称之为页面作者样式.
- 浏览器的用户,可以使用自定义样式表定制使用体验,称之为用户样式
对应的重要性顺序依次为: 页面作者样式>用户样式> 用户代理样式
我们来看一个示例
例如现在有页面作者样式表和用户代理样式表中存在属性的冲突,那么会以作者样式表优先
p{
color : red;
display: inline-block;
}
可以明显的看到,作者样式表和用户代理样式表中同时存在的idsplay属性的设置,最终作者样式表干掉了用户代理样式表中冲突的属性,这就是第一步,根据不同源的重要性来决定应用哪一个源的样式.
3. 比较优先级
那么接下来,如果是在在同一个源中又样式声明冲突怎么办呢? 此时就会进行样式声明的优先级比较.
例如:
<div class='test'>
<h1>test</h1>
<div>
.test h1{font-size: 50px
}
h1 {
font-size: 20px;
}
在上面的代码中,同属于页面作者样式,源的重要性是相同的,此时会以选择器的权重来比较重要性.
很明显,上面的选择器的权重要大于下面的选择器,因此最终标题呈现50px.
可以看到,落败的作者样式在Element Style中会被划掉
有关选择器的权重计算方式,不清楚的同学,可以进入此传送门: Specificity - CSS | MDN
4.比较次序
经历了上面两个步骤,大多数的样式声明能够被确定下来,但是还剩下最后一种情况,那就是样式声明即是同源,权重也相同.
此时就会进入第三个步骤,比较样式声明的次序
举个例子:
h1{
font-size: 50px;
}
h1 {font-size: 20px;
}
在上面的代码中,同样都是页面作者样式,选择器的权重也想通,此时位于下面的样式声明会层叠掉上面的那一条样式声明,最终会应用20px这一条属性值
至此,样式声明中存在冲突的所有情况,就全部被解决了.
5.使用继承
层叠冲突这一步完成后,解决了相同元素被声明了多条样式规则,究竟应用哪一条样式规则的问题.那么如果没有声明的属性呢?此时就是用默认值吗?
不是的.此时还有第三个步骤,那就是使用继承而来的值
例如:
<div>
<p>Lorem ipsum dolor sit amet.</p>
</div>
div {
color: red;
}
在上面的代码中,我们针对div 设置color属性值为红色,而针对p元素我们没有声明任何的属性,但是由于color是可以继承的,因此p元素会从父元素的同属性的计算值继承到color属性的值
来看下面的一个例子:
<div class="test">
<div>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
div {
color: red;
}
.test{
color: blue;
}
因为这里并不涉及到选中p元素声明color值,而是从父元素上面继承到color对应的值,因此这里是谁近就听谁的,初学者往往会产生混淆,又去比较权重,但是这里根本不会涉及到权重比较,因为压根儿就没有选中到p元素.
另外哪些属性能够继承?
关于这一点的话,大家可以在MDN上很轻松的查阅到,例如我们以text-align 为例,如下图所示:
6.使用默认值
目前走到这一步,如果属性值都还不能确定下来,那么久只能是使用默认值了.
如下图所示:
前面我们也说过,一个HTML元素要在浏览器中渲染出来,必须具备所有的CSS属性值,但是绝大部分我们是不会去设置的,用户代理样式表里面也不会去设置,也无法从继承拿到,因此最终都是用默认值
好了,这就是关于CSS属性计算过程的所有知识了.
7.面试题
下面的代码,最终渲染出来的效果,a元素是什么颜色?p元素又是什么颜色
<div>
<a href="">test</a>
<p>test</p>
</div>
为什么会呈现这样的效果?
实际上原因很简单,因为a元素在用户代理样式表中已经设置了color属性对应的值也就是默认样式,因此会应用此声明值,而在p元素中无论是作者样式表还是用户代理样式表,都没有对此属性进行声明,然而由于color属性是可以继承的,因此最终p元素的color属性值通过持恒来自于父元素.