问题
CSS 的 cascade,即是指某一选择器被多条 CSS 规则指定并有冲突时,指导浏览器应该选择哪条规则去执行。
比如给定一个元素:
<h1 id="page-title" class="title">Wombat Coffee Roasters</h1>
有不同来源的多条 CSS 规则:
// 来源 1
#page-title {
font-family: sans-serif;
}
// 来源 2
#page-title {
font-family: serif;
}
// 不同选择器
.title {
font-family: monospace;
}
每个规则集中的选择器都是 #page-title
,但是它们的内容是冲突的。
规则
哪些 CSS 实体会参与 cascade 规则?
CSS declarations 会参与。
这意味着部分没有 declaration 的 at-rule,如 @font-face
,它的 descriptor 不参与 cascade;它会作为一个整体参与 cascade,如果有多个 descriptor 一样的 at-rule,浏览器会自动选择最合适的。
另外有一部分带 declaration 的 at-rule,@media
、@document
及 @supports
会参与 cascade。@keyframes
不会,跟 @font-face
一样作为一个整体去参与。
@import
及 @charset
有自己特殊的规则。
CSS Origin
CSS 有三种 origin 的样式表:
- User-agent stylesheets:浏览器默认的样式表。比如如果你不指定
<li>
的样式时,它默认的list-style-type
在浏览器中一般默认为disc
,即一个小圆点 - Author stylesheets:最常见的样式表,即网页中指定的样式
- User stylesheets:用户样式表,设计上是为了提供给用户指定一个默认样式表的能力,这个样式表可以覆盖 User-agent 样式表。但是实际上浏览器并不怎么支持这种模式,比如 Chrome 移除了 User stylesheet 的支持。现实中用得非常少,目前看到的是可以通过浏览器扩展的 API 接口来指定,比如 Chrome 的
insertCSS
接口 中的cssOrigin
参数,Firefox 中亦有相应参数。但是它们默认都是使用 author 类型。Chrome User Style 插件 Stylus 也是用的 author 类型
User stylesheets 在实际中使用得很少,下面不做讨论。
Cascading Algorithm
对于一个特定的 DOM 元素,如果存在有冲突的 declaration,是这样判定优先级的:
(图片来自 CSS in Depth 第一章)
其中的第一个判断在本文的讨论范围内。对于不同的 origin 及其 !important
属性,优先级如下:
Order | Origin | Importance |
---|---|---|
1 | user agent | normal |
2 | author | normal |
3 | animations | |
4 | author | !important |
5 | user agent | !important (rarely used) |
6 | transitions |
数值越大的优先级越高。这套规则里面最常用来写特定的样式(author stylesheet)来覆盖默认的样式(user-agent stylesheet),比如下面的例子中将 <a>
元素以按钮的形式展现:
#main-nav a {
color: white;
background-color: #13a4a4;
padding: 5px;
border-radius: 2px;
text-decoration: none;
}
对于 origin 相同的 declaration,他们的判断逻辑在 CSS: Concept: Cascade: Specificity 中描述。
关于 animation 及 transition 部分的内容,在相关的条目中描述。!important
有自己的 条目。