一个dom元素的样式来源可以有很多, 比如开发者定义的、浏览器默认的, 或者有多个选择器选中了同一个元素; 当多个来源中的属性有重合时, 究竟应用哪个来源中的属性, 这是css的核心问题。
层叠是css的核心, 从层叠样式表
这个名字上就能看出来, 它是一个定义了如何合并来自多个源的属性值的算法。
重要性(Importance)
重要性是凌驾于所有其他层叠规则之上的方法, 通过在属性值后加!important
, 将这条css属性声明 设置为important的。
important
的属性一定覆盖normal
属性- 当都声明为
!important
或者都没有声明为!important
时, 往下走吧
源(Origin)
一般的, css的源被分为三类:
类别 | 描述 |
---|---|
用户代理/浏览器样式表(User-agent stylesheets) | 浏览器样式表是是浏览器提供的默认样式。每个浏览器都有一套自己的默认样式,用于在未明确指定样式时显示HTML元素。例如,大多数浏览器会默认将<h1> 元素显示为大号加粗字体,<a> 元素显示为蓝色并在鼠标悬停时下划线等。这些默认样式的目的是为了在没有CSS的情况下提供一个基本的、可读的文档结构。 |
作者/开发者样式表(Author stylesheets) | web开发者为文档设置的样式, 定义了网页的外观。 |
用户样式表(User stylesheets) | Web 浏览器允许用户编写 CSS 样式表,浏览器使用这些样式表来覆盖页面设计者所做的样式选择。但目前几乎被淘汰,如chrome不再支持。究其原因, 现代的网页早以不像是古早时候只是一个结构简单文档, 而是变成了应用程序。开发者样式越来越复杂越来越完善, 定义用户样式大概率不会让网页更好, 反而是破坏了网页的正常效果、设计主题。 所谓用户样式, 到现在, 只在markdown这样的简单排版文档里还有存活空间。 |
层叠的顺序如下图:
Order (low to high) | Origin | Importance |
---|---|---|
1 | user-agent (browser) | normal |
2 | user | normal |
3 | author (developer) | normal |
4 | CSS @keyframe animations | |
5 | author (developer) | !important |
6 | user | !important |
7 | user-agent (browser) | !important |
8 | CSS transitions |
可以看到, 当开发者样式与浏览器样式冲突时, 开发者样式的优先级更高; 但当应用了!important
时, 结果将相反, 应用了!important
的开发者样式无法覆盖应用了!improtant
的浏览器样式。
当源相同时, 那么继续往下走
优先级(Specificity)
当css属性具有相同的源(origin)时, 我们会开始为css属性计算得到一个优先级, 优先级高的会覆盖掉优先级低的。
行内样式
一般来说所有css在一个样式表环境里; 但在web开发者的角色里, 还可以为dom元素设置行内样式。
行内样式总会覆盖外部样式表的任何样式,因此可看作是具有最高的优先级。
优先级计算
优先级的计算原则是: 选择器越具体, 优先级越高。
比如
#text {...}
p {...}
<p id="text"></p>
这里的两个选择器都能选择这个p
元素, 但一个是标签选择器, 泛泛地选中了文档中所有的p标签; 而#text
选中具有id=text
的元素, 要比标签选择具体的非常多。 在这种情况下, id选择器的优先级比标签选择器要高。
选择器的优先级被量化为一个长度为3的元组: (x, y, z)
, 进行字典序比较。
这里的字典序比较可能造成误解。
这里的字典序比较指的是, 索引小的权重大的比较方式, 只有当前位相同才会比较下一位。
比如
[2, 1, 1] > [1, 3, 3]
, 因为首位2 > 1
比如
[2, 2, 1] > [2, 1, 3]
, 因为首位相同, 所以比较第二位,2 > 1
优先级元组(x, y, z)
中三个位置分别代表的意义是 :
: 选择器中 ID
选择器的数量:选择器中 (类选择器、属性选择器、伪类选择器)的数量 : 选择器中(标签选择器、伪元素选择器)的数量
给出以下例子帮助了解
#app {...} // (1, 0, 0)
.box {...} // (0, 1, 0)
div {...} // (0, 0, 1)
#app .box {...} // (1, 1, 0)
#app > .list > a {...} // (1, 1, 1)
a:hover {...} // (0, 1, 1)
#app::before {...} // (1, 0, 1)
.item.selected {...} // (0, 2, 0)
继承(inheritance)
参考
CSS 层叠 - CSS:层叠样式表 | MDN (mozilla.org)
层叠、优先级与继承 - 学习 Web 开发 | MDN (mozilla.org)
优先级 - CSS:层叠样式表 | MDN (mozilla.org)