层叠

CSS 播客 - 004:层叠

CSS 代表层叠样式表。层叠是解决冲突的算法,当多个 CSS 规则应用于 HTML 元素时。这就是使用以下 CSS 样式化的按钮文本将为蓝色的原因。

button {
  color: red;
}

button {
  color: blue;
}

了解层叠算法有助于您了解浏览器如何解决此类冲突。层叠算法分为 4 个不同的阶段。

  1. 位置和外观顺序:CSS 规则出现的位置顺序
  2. 特异性:一种算法,用于确定哪个 CSS 选择器具有最强的匹配项
  3. 来源:CSS 出现的时间顺序以及来源,无论是浏览器样式、浏览器扩展程序的 CSS 还是您编写的 CSS
  4. 重要性:某些 CSS 规则的权重高于其他规则,尤其是 !important 规则类型

位置和外观顺序

层叠在计算冲突解决时,会考虑 CSS 规则出现的位置顺序和外观方式。

本课程开始时的演示是位置最直接的示例。有两个规则的选择器具有相同的特异性,因此最后一个声明的规则获胜。

样式可以来自 HTML 页面上的各种来源,例如 <link> 标签、嵌入的 <style> 标签以及元素 style 属性中定义的内联 CSS。

如果您在 HTML 页面顶部有一个包含 CSS 的 <link>,然后在页面底部有另一个包含 CSS 的 <link>:底部的 <link> 将具有最高的特异性。嵌入的 <style> 元素也是如此。它们越往下页,特异性就越高。

按钮具有蓝色背景,由 <link /> 元素包含的 CSS 定义。将按钮设置为深色的 CSS 规则位于第二个链接的样式表中,并因其稍后的位置而应用。

此排序也适用于嵌入的 <style> 元素。如果它们在 <link> 之前声明,则链接样式表的 CSS 将具有最高的特异性。

<style> 元素在 <head> 中声明,而 <link /> 元素在 <body> 中声明。这意味着它比 <style> 元素具有更高的特异性

内联 style 属性及其声明的 CSS 将覆盖所有其他 CSS,无论其位置如何,除非声明定义了 !important

位置也适用于 CSS 规则的顺序。在此示例中,元素将具有紫色背景,因为 background: purple 是最后声明的。由于绿色背景在紫色背景之前声明,因此现在被浏览器忽略。

.my-element {
  background: green;
  background: purple;
}

能够为同一属性指定两个值可以成为为不支持特定值的浏览器创建后备的简单方法。在下一个示例中,font-size 声明了两次。如果浏览器中支持 clamp(),则之前的 font-size 声明将被丢弃。如果浏览器不支持 clamp(),则将遵守初始声明,字体大小将为 1.5rem

.my-element {
  font-size: 1.5rem;
  font-size: clamp(1.5rem, 1rem + 3vw, 2rem);
}

检查您的理解

测试您对层叠的知识

如果您在页面上有以下 HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="/styles.css" />
  </head>
  <body>
    <button>I am a button</button>
    <style>
      button {
        background: pink;
      }
    </style>
  </body>
</html>

styles.css 内部,是以下 CSS 规则

button {
  background: yellow;
}

按钮的背景是什么颜色?

粉色
嵌入的 <style> 来源比 <link> 标签更靠下,因此虽然 button 的特异性相同,但样式规则的位置使其获胜。
黄色
对于 HTML 文档,黄色按钮背景可能首先被读取,但是稍后发现了相同特异性的较新规则,从而使此规则不适用于按钮。

特异性

特异性是一种算法,用于确定哪个 CSS 选择器是最具体的,使用加权或评分系统来进行这些计算。通过使规则更具体,即使稍后在 CSS 中出现与选择器匹配的其他 CSS,您也可以使其应用。

下一课中,您可以了解如何计算特异性的详细信息,但是记住一些事项将有助于您避免过多的特异性问题。

CSS 定位元素上的类将使该规则更具体,因此被视为比仅定位元素的 CSS 更重要。这意味着使用以下 CSS,即使两个规则都匹配,并且 h1 选择器的规则在样式表中稍后出现,h1 也将显示为红色。

<h1 class="my-element">Heading</h1>
.my-element {
  color: red;
}

h1 {
  color: blue;
}

id 使 CSS 更加具体,因此应用于 ID 的样式将覆盖以许多其他方式应用的样式。这是通常不建议将样式附加到 id 的原因之一。这可能会使您难以使用其他内容覆盖该样式。

特异性是累积的

正如您在下一课中可以发现的那样,每种类型的选择器都会获得指示其特异性的点数,用于定位元素的所有选择器的点数会加在一起。这意味着,如果您使用选择器列表(例如 a.my-class.another-class[href]:hover)定位元素,您会得到一些很难用其他 CSS 覆盖的东西。因此,为了帮助使您的 CSS 更具可重用性,最好尽可能保持选择器简单。在需要时使用特异性来获取元素,但如果可以,请始终考虑重构长而特定的选择器列表。

来源

您编写的 CSS 不是应用于页面的唯一 CSS。层叠考虑了 CSS 的来源。此来源包括浏览器的内部样式表、浏览器扩展程序或操作系统添加的样式以及您编写的 CSS。这些来源的特异性顺序,从最不具体到最具体,如下所示

  1. 用户代理基本样式。这些是浏览器默认应用于 HTML 元素的样式。
  2. 本地用户样式。这些样式可能来自操作系统级别,例如基本字体大小或减少动画的首选项。它们也可能来自浏览器扩展程序,例如允许用户为网页编写自己的自定义 CSS 的浏览器扩展程序。
  3. 编写的 CSS。您编写的 CSS。
  4. 编写的 !important。您添加到编写的声明中的任何 !important
  5. 本地用户样式 !important。来自操作系统级别或浏览器扩展程序级别 CSS 的任何 !important
  6. 用户代理 !important。浏览器提供的默认 CSS 中定义的任何 !important
A visual demonstration of the order of origins as also explained in the list.

如果您在您编写的 CSS 中有一个 !important 规则类型,并且用户在其自定义 CSS 中有一个 !important 规则类型,那么谁的 CSS 获胜?

检查您的理解

测试您对层叠来源的知识

测试您对层叠来源的知识,考虑来自各种来源的以下样式规则

用户代理样式

h1 { margin-block-start: 0.83em; }

Bootstrap

h1 { margin-block-start: 20px; }

页面作者样式

h1 { margin-block-start: 2ch; }

@media (max-width: 480px) {
  h1 { margin-block-start: 1ch; }
}

用户自定义样式

h1 { margin-block-start: 2rem !important; }

然后,给定以下 HTML

<h1>Lorem ipsum</h1>

h1 的最终 margin-block-start 是什么?

20px
Bootstrap 是编写来源的一部分,它输给了重要的本地用户样式。
0.83em
用户代理样式来源输给了重要的本地用户样式。
2rem
!important 用户自定义样式具有最具体的来源。
2ch
此作者样式是编写来源的一部分,它输给了重要的本地用户样式。
1ch
此作者样式是编写来源的一部分,它输给了重要的本地用户样式。

重要性

并非所有 CSS 规则的计算方式都相同,或者给予相同的特异性。

重要性顺序,从最不重要到最重要,如下所示

  1. 普通规则类型,例如 font-sizebackgroundcolor
  2. animation 规则类型
  3. !important 规则类型(遵循与来源相同的顺序)
  4. transition 规则类型

活动动画和过渡规则类型的优先级高于普通规则。在过渡的情况下,优先级高于 !important 规则类型。这是因为当动画或过渡变为活动状态时,其预期行为是更改视觉状态。

使用 DevTools 找出某些 CSS 未应用的原因

浏览器 DevTools 通常会显示所有可能与元素匹配的 CSS,其中未使用的 CSS 会被划掉。

An image of browser DevTools with overwritten CSS crossed out

如果您期望应用的 CSS 根本没有出现,那么它与元素不匹配。在这种情况下,您需要查看其他地方,可能是类或元素名称中的拼写错误或某些无效 CSS。

检查您的理解

测试您对层叠的知识

层叠可用于...

在多个样式应用于元素时解决冲突。
这是其主要目标之一,冲突解决。
确保在绘制时每个属性只有一个样式值。
文本只能是一种颜色,“层叠”是一种确定它应该是哪种颜色的方法。
对样式规则进行评分和加权。
评分和加权是“层叠”排序阶段的一部分。
对样式属性进行排序和筛选。
排序和筛选是“层叠”的各个阶段,有助于理解冲突解决的各个方面。

资源