前言
石匠敲击石头的第 4 次
CSS 英文全称为 Cascading Style Sheets,中文翻译为 "层叠样式表",那究竟什么是层叠?我却说不出个所以然,所以打算写一篇文章来梳理一下,如果哪里写的有问题欢迎指出。
层叠是什么
层叠是指多个样式规则同时作用于同一个元素时,浏览器通过一套明确的优先级规则来决定最终生效的样式。
简单来说就是层叠就是浏览器应用样式的优先级规则。
下图是层叠优先级规则判断的流程。
上图中流程简单来说会按照以下规则顺序来解决冲突。
- 样式表的来源
- 选择器优先级
- 在源码中的顺序
样式表的来源
样式表通常有以下的来源:
- 用户代理样式表(User Agent Styles): 浏览器的默认样式,例如:
<h1>
标签自带加粗和字体大小以及外边距的默认样式 - 用户样式表(User Styles): 用户通过浏览器插件(如
Stylus
插件)、浏览器设置或开发者工具定义的样式,较少见 - 作者样式表(Author Styles): 网页的开发者(即 "作者")编写的样式表,根据定义位置可以细分为如下样式表
- 外部样式表:通过
<link>
标签引入的外部 CSS 文件 - 内部样式:在 HTML 内部使用
<style>
标签定义的样式 - 行内样式(内联样式):通过元素的
style
属性直接定义的样式
- 外部样式表:通过
样式表的优先级
样式表的优先级由低到高如下:
- 用户代理样式表
- 用户样式表
- 作者样式表
- 外部样式表
- 内部样式表
- 行内样式表(内联样式表)
- 外部样式表的
!important
- 内部样式表的
!important
- 行内样式(内联样式)的
!important
⚠️ 注意: 不推荐在行内样式中使用 !important
,因为优先级最高,无法被覆盖。
选择器优先级
选择器的优先级由低到高如下:
选择器类型 | 优先级标记 |
---|---|
通用选择器(* )和组合选择器(> 、+ 、~ ) |
(0,0,0) |
标签选择器(p ) |
(0,0,1) |
伪类选择器(:hover )、属性选择器([type="text"] )、类选择器(.class ) |
(0,1,0) |
ID 选择器(#id ) |
(1,0,0) |
同时使用多种类型的选择器会让它们的优先级标记进行个数计算,例如 (1,2,2)
表示选择器由 1 个 ID 选择器、2 个类选择器、2 个标签选择器组成。
源码顺序
当两个声明的来源和选择器的优先级都相同,这时浏览器会根据声明在源码中的顺序,哪个声明最晚出现,则使用哪个声明。
例如:给链接添加样式的时候需要按照正确的顺序来书写选择器。
❌ 错误的顺序
css
a:hover {
text-decoration: underline;
}
a:link {
color: blue;
text-decoration: none;
}
a:visited {
color: purple;
}
a:active {
color: red;
}
上述代码中,链接的四种状态都来自于相同的来源(作者样式表,并且在同一个文件中),并且选择器的优先级都为 (0,1,1)
,所以浏览器根据在源码中的顺序来判断使用哪个声明。
所以导致了 a:hover
选择器中的 text-decoration: underline;
声明被后面的 a:link
选择器中的 text-decoration: none;
所覆盖。
✔️正确的顺序
css
a:link {
color: blue;
text-decoration: none;
}
a:visited {
color: purple;
}
a:hover {
text-decoration: underline;
}
a:active {
color: red;
}
可以使用顺序记忆口诀:"LoVe/HAte"("爱/恨"),其中 L 表示 link
,V 表示 visited
,H 表示 hover
,A
表示 active
。
最佳实践
- 不使用 ID 选择器来添加样式: 因为 ID 选择器的优先级过高,需要使用其它的 ID 选择器或者使用
!important
才能覆盖,并且也不利于样式的复用,因为 ID 属性是唯一的 - 不使用
!important
: 比 ID 选择器更难覆盖,如果需要覆盖就需要使用!important
,如果很多声明都添加了!important
,就又会按照层叠优先级规则判断的流程的顺序进行比较
⚠️ 注意: 在特殊情况中(例如需要使用 JavaScript 通过 ID 选择器快速定位某个元素,或者需要使用 !important
才能覆盖第三方组件库的样式),可以不必死板遵守上述的两条建议
总结
- 层叠就是浏览器应用样式的优先级规则 ,大致的规则流程顺序如下
- 样式表的来源
- 选择器优先级
- 在源码中的顺序
- 最佳实践
- 不使用 ID 选择器来添加样式
- 不使用
!important