首先我们在HTML中使用h1标签展现标题时,我们没有设置该h1的任何央视,但是却能看到该h1由一定的默认样式,例如有默认的字体大小、默认的颜色。那么问题来了,我们这个 h1 元素上面除了有默认字体大小、默认颜色等属性以外,究竟还有哪些属性呢?
答案是该元素会有css的全部属性,我们可以打开浏览器的开发者面板,选择【元素】,切换到【计算样式】,之后勾选【全部显示】,此时你就能看到在此h1上面所有的css属性对应的值。
其实,我们所书写的任何一个HTML元素,实际上都有完整的一整套css样式。只不过你没有书写的样式,大概率可能会用默认值。但是也存在没有设置值,却不使用默认值的情况。因此我们要了解"css属性的计算过程"。
总的来讲,属性值的计算过程分为以下步骤:
- 确定声明值
- 层叠冲突
- 使用继承
- 使用默认值
确定声明值
首先第一步时确定声明值,所谓声明值就是作者自己书写的css样式,例如:
p{
color : red;
}
这里我们声明了p元素为红色,那么就会应用此属性设置。
除了作者样式表,浏览器还存在"用户代理样式表",就是浏览器内置了一套样式表。
这些值目前来讲没有冲突,因此最终会应用这些属性值。
层叠冲突
在确定声明值时,可能出现一种情况,那就是声明的样式规则发生了冲突。
此时会进入解决层叠冲突的流程。而这一步又可以细分为下面这三个步骤:
- 比较源的重要性
- 比较优先级
- 比较次序
比较源的重要性
样式表的源总体有三种:
- 浏览器有一个基本的样式表给任何网页设置默认样式。称之为用户代理样式
- 网页的作者可以定义文档的样式,这是最常见的样式表,称之为页面作者样式
- 浏览器的用户,可以使用自定义样式表定制使用体验,称之为用户样式
重要性次序为:页面作者样式 > 用户样式 > 用户代理样式
我们来看一个案例
例如现在有页面作者样式表和用户代理样式表存在属性冲突,那么会议作者样式表优先。
p{
color : red;
display: inline-block;
}
可以明显的看到,作者样式表和用户代理样式表中同时存在的 display 属性的设置,最终作者样式表干掉了用户代理样式表中冲突的属性。这就是第一步,根据不同源的重要性来决定应用哪一个源的样式。
比较优先级
如果在同一个源中有样式声明冲突怎么办呢?此时就会进行样式的优先级比较。
例如:
<div class="test">
<h1>test</h1>
</div>
.test h1{
font-size: 50px;
}
h1 {
font-size: 20px;
}
在上面的代码中,同属于页面作者样式,源的重要性是相同的,此时会以选择器的权重来比较重要性。
很明显,上面的选择器的权重要大于下面的选择器,因此最终标题呈现为 50px。
关于选择器权重排序: !important >行内样式(style)>id>类(class)|伪类(a:link)|属性(p[class="blue"])>标签(div、h1)>通配符(*)。继承没有权重
比较次序
经历了上面两个步骤,大多数的样式声明能够被确定下来。但是还剩下最后一种情况,那就是样式声明既是同源,权重也相同。
此时就会进入第三个步骤,比较样式声明的次序。
h1 {
font-size: 50px;
}
h1 {
font-size: 20px;
}
在上面的代码中,同样是页面作者样式,选择器的权重也相同,此时位于下面的样式声明会层叠掉上面那层样式声明。
使用继承
层叠冲突完成后,解决了相同的元素被声明了多条样式规则究竟应用哪条样式规则的问题。那么如果没有声明的属性呢?此时就使用默认值吗?其实还有第三个步骤,就是使用继承而来的值.
例如:
<div class="test">
<div>
<p>Lorem ipsum dolor sit amet.</p>
</div>
</div>
div {
color: red;
}
.test{
color: blue;
}
因为这里并不涉及到选中 p 元素声明 color 值,而是从父元素上面继承到 color 对应的值,因此这里是谁近就听谁的。
并不是所有属性都能继承,可以在MDN上查阅属性是否可以继承。
使用默认值
如果到这一步属性值还不能确定下来,就只能使用默认值了。
面试题
<div>
<a href="">test</a>
<p>test</p>
</div>
div {
color: red;
}
实际上原因很简单,因为 a 元素在用户代理样式表中已经设置了 color 属性对应的值,因此会应用此声明值。而在 p 元素中无论是作者样式表还是用户代理样式表,都没有对此属性进行声明,然而由于 color 属性是可以继承的,因此最终 p 元素的 color 属性值通过继承来自于父元素。