CSS: Concept: Cascade

20th August 2020 at 2:19pm

问题

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 属性,优先级如下:

OrderOriginImportance
1user agentnormal
2authornormal
3animations
4author!important
5user agent!important (rarely used)
6transitions

数值越大的优先级越高。这套规则里面最常用来写特定的样式(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 有自己的 条目

Resources

TOC

TOC