层叠样式表

本课程旨在向您介绍层叠样式表,这是一项更高级的功能,它建立在CSS 层叠CSS 特异性的基本概念之上。

如果您是 CSS 新手,学习本课程可能会感觉不太相关,而且比课程的其他部分更学术化。但是,了解层叠样式表的基础知识,以便在您的项目中遇到它们时,将会很有帮助。您使用 CSS 越多,了解层叠样式表以及如何利用其强大功能,就能避免在管理来自不同方、插件和开发团队的 CSS 代码库时,遇到很多麻烦。

当您使用来自多个来源的 CSS 时,层叠样式表最为相关,这时会出现冲突的 CSS 选择器和竞争的特异性,或者您正在考虑使用!important

先决条件 了解 CSS 的工作原理,包括层叠和特异性(学习CSS 初步层叠、特异性以及继承)。
目标 了解层叠样式表的工作原理。

对于应用于元素的每个 CSS 属性,只能有一个值。您可以通过在浏览器开发者工具中检查元素来查看应用于元素的所有属性值。该工具的“样式”面板显示应用于正在检查的元素的所有属性值,以及匹配的选择器和 CSS 源文件。具有优先级的来源中的选择器将其值应用于匹配的元素。

除了应用的样式外,“样式”面板还会显示被划掉的匹配所选元素但未应用的值,这是由于层叠、特异性或源顺序导致的。被划掉的样式可能来自具有优先级的相同来源,但特异性较低,或者具有匹配的来源和特异性,但在代码库中较早找到。对于任何应用的属性值,可能有多个声明从许多不同的来源被划掉。如果您看到一个被划掉的样式具有特异性更高的选择器,则表示该值在来源或重要性方面存在不足。

通常,随着站点复杂性的增加,样式表的数量也会增加,这使得样式表的源顺序变得更加重要和复杂。层叠样式表简化了跨此类代码库维护样式表的过程。层叠样式表是明确的特异性容器,提供更简单、更强大的对最终应用的 CSS 声明的控制,使 Web 开发人员能够优先处理 CSS 部分,而无需与特异性作斗争。

要理解层叠样式表,您必须充分理解 CSS 层叠。以下部分快速回顾了重要的层叠概念。

层叠概念回顾

CSS 中的“C”代表“层叠”。它是样式层叠在一起的方法。用户代理会执行几个明确定义的步骤来确定为每个元素的每个属性分配的值。我们将在此处简要列出这些步骤,然后深入探讨步骤 4,**层叠样式表**,这是您来这里学习的内容

  1. **相关性:**查找所有具有元素选择器匹配的声明块。
  2. **重要性:**根据规则是普通规则还是重要规则进行排序。重要样式是设置了!important标志的样式。
  3. **来源:**在两个重要性桶中的每一个中,按作者、用户或用户代理来源对规则进行排序。
  4. **层叠样式表:**在六个来源重要性桶中的每一个中,按层叠样式表排序。普通声明的层级顺序是从创建的第一个层到最后一个层,然后是未分层的普通样式。重要样式的顺序相反,未分层的重要样式具有最低优先级。
  5. **特异性:**对于具有优先级的来源层中相互竞争的样式,按特异性对声明进行排序。
  6. **作用域邻近性**:当具有优先级的来源层中的两个选择器具有相同的特异性时,作用域规则中距作用域根节点 DOM 层级跃迁次数最少的属性值获胜。有关更多详细信息和示例,请参阅如何解决@scope冲突

  7. 出现顺序:当起源层中两个具有优先级的选择器具有相同的特异性和范围接近度时,来自最后声明的选择器(具有最高特异性)的属性值获胜。

对于每个步骤,只有“仍在运行”的声明才能继续在下一步中“竞争”。如果只有一个声明在运行,它将“获胜”,随后的步骤将变得毫无意义。

起源和层叠

有三种层叠起源类型:用户代理样式表、用户样式表和作者样式表。浏览器根据起源和重要性将每个声明排序到六个起源桶中。层叠有八个级别:六个起源桶、正在过渡的属性和正在动画的属性。优先级顺序从普通的用户代理样式(优先级最低)到当前应用动画内的样式,再到重要的用户代理样式,最后是正在过渡的样式(优先级最高)。

  1. 用户代理普通样式
  2. 用户普通样式
  3. 作者普通样式
  4. 正在动画的样式
  5. 作者重要样式
  6. 用户重要样式
  7. 用户代理重要样式
  8. 正在过渡的样式

“用户代理”是浏览器。“用户”是网站访问者。“作者”是您,即开发者。使用<style>元素直接在元素上声明的样式是作者样式。不包括动画和过渡样式,用户代理普通样式的优先级最低;用户代理重要样式的优先级最高。

起源和特异性

对于每个属性,获胜的声明来自根据权重(普通或重要)具有优先级的起源。暂时忽略层,来自优先级最高的起源的值将被应用。如果获胜的起源对某个元素有多个属性声明,则会比较这些竞争属性值的选择器特异性。不同起源的选择器之间永远不会比较特异性。

在下面的示例中,有两个链接。第一个没有应用任何作者样式,因此只应用用户代理样式(以及您的个人用户样式,如果有)。第二个通过作者样式设置了text-decorationcolor,即使作者样式表中的选择器特异性为0-0-0。作者样式“获胜”的原因是,当来自不同起源的样式发生冲突时,将应用来自具有优先级的起源的规则,而不管不具有优先级的起源中的特异性如何。

在撰写本文时,用户代理样式表中“竞争”的选择器是a:any-link,其特异性权重为0-1-1。虽然这大于作者样式表中的0-0-0选择器,但即使您当前用户代理中的选择器不同,也不要紧:永远不会比较来自作者和用户代理起源的特异性权重。详细了解如何计算特异性权重

起源优先级始终高于选择器特异性。如果元素属性在多个起源中使用普通样式声明进行样式设置,则作者样式表将始终覆盖在用户或用户代理样式表中声明的冗余普通属性。如果样式很重要,则用户代理样式表将始终优先于作者和用户样式。层叠起源优先级确保起源之间的特异性冲突永远不会发生。

在继续之前,还有一点需要注意:只有当优先级起源中竞争的声明具有相同特异性时,出现顺序才会变得相关。

层叠样式表概述

现在我们了解了“层叠起源优先级”,但什么是“层叠层优先级”?我们将通过解决什么是层叠层、它们是如何排序的以及样式是如何分配给层叠层的来回答这个问题。我们将介绍常规层嵌套层和匿名层。让我们首先讨论什么是层叠层以及它们解决了哪些问题。

层叠层优先级顺序

与我们根据起源和重要性有六个优先级级别类似,层叠层使我们能够在这些起源中的任何一个内创建子起源级别的优先级。

在六个起源桶中的每一个中,都可以有多个层叠层。层创建顺序非常重要。正是创建顺序决定了起源内层之间的优先级顺序。

在普通起源桶中,层按每个层的创建顺序排序。优先级顺序是从第一个创建的层到最后一个层,然后是未分层的普通样式。

对于重要样式,此顺序会反转。所有未分层的重要样式会一起层叠到一个隐式层中,该层优先于所有非过渡普通样式。未分层的重要样式的优先级低于任何重要的分层样式。在相同起源中,较早声明的层中的重要样式优先于后续声明的层中的重要样式。

在本教程的其余部分,我们将讨论范围限制在作者样式,但请记住,层也可以存在于用户和用户代理样式表中。

层叠层可以解决的问题

大型代码库可能来自多个团队、组件库、框架和第三方。无论包含多少个样式表,所有这些样式都会在一个起源中层叠在一起:作者样式表。

来自许多来源的样式层叠在一起,特别是来自不一起工作的团队的样式,可能会造成问题。不同的团队可能具有不同的方法;一个团队可能将降低特异性作为最佳实践,而另一个团队可能将每个选择器中包含一个id作为标准。

特异性冲突可能迅速升级。Web 开发人员可能会通过添加!important标志来创建一个“快速修复”。虽然这可能感觉像一个简单的解决方案,但它通常只是将特异性冲突从普通声明转移到重要声明。

层叠起源在用户、用户代理和作者样式之间提供权力平衡的方式,层叠层也提供了一种结构化的方法来组织和平衡单个起源内的关注点,就好像起源中的每个层都是一个子起源一样。可以为每个团队、组件和第三方创建一个层,优先级基于层顺序。

层内的规则层叠在一起,不会与层外的样式规则竞争。层叠层使能够优先考虑整个样式表而不是其他样式表,而无需担心这些子起源之间的特异性。

层优先级始终高于选择器特异性。具有优先级的层中的样式优先于具有较低优先级的层。失败层中选择器的特异性无关紧要。特异性对于层内竞争的属性值仍然很重要,但层之间没有特异性问题,因为只考虑每个属性的最高优先级层。

嵌套层叠层可以解决的问题

层叠层允许创建嵌套层。每个层叠层都可以包含嵌套层。

例如,可以将组件库导入到components层中。常规层叠层会将组件库添加到作者起源,消除与其他作者样式之间的任何特异性冲突。在components层中,开发人员可以选择定义各种主题,每个主题作为一个单独的嵌套层。这些嵌套主题层的顺序可以根据媒体查询(请参阅下面的层创建和媒体查询部分)来定义,例如视口大小或方向。这些嵌套层提供了一种创建基于特异性不冲突的主题的方法。

嵌套层的功能对于任何从事组件库、框架、第三方小部件和主题开发的人员都非常有用。

创建嵌套层的功能还消除了对层名称冲突的担忧。我们将在嵌套层部分介绍这一点。

“作者可以创建层来表示元素默认值、第三方库、主题、组件、覆盖和其他样式问题,并且能够以显式方式重新排序层的层叠,而无需更改每个层内的选择器或特异性,或依赖出现顺序来解决跨层的冲突。”

——层叠和继承规范

创建层叠样式表

可以使用以下任何一种方法创建层

  • 使用@layer语句@规则,声明使用@layer后跟一个或多个层的名称的层。这会创建命名层,而不会为其分配任何样式。
  • @layer块@规则,其中块中的所有样式都添加到命名或未命名的层中。
  • 使用layer关键字或layer()函数的@import规则,它将导入文件的內容分配到该层。

这三种方法都会创建层,前提是尚未初始化具有该名称的层。如果在@layer@规则或带有layer()@import中未提供层名称,则会创建一个新的匿名(未命名)层。

注意:层的优先级顺序是创建它们的顺序。不在层中的样式或“未分层样式”会一起层叠到最终的隐式标签中。

在讨论嵌套层之前,让我们更详细地介绍创建层的这三种方法。

用于命名层的@layer语句@规则

层的顺序由层在 CSS 中出现的顺序设置。使用@layer后跟一个或多个层的名称来声明层,而无需分配任何样式,是定义层顺序的一种方法。

@layer CSS @规则用于声明层叠层,并在存在多个层叠层时定义优先级顺序。以下@规则按列表顺序声明了三个层

css
@layer theme, layout, utilities;

您通常希望将 CSS 的第一行设置为此@layer声明(当然,使用对您的站点有意义的层名称),以便完全控制层排序。

如果上述语句是站点 CSS 的第一行,则层顺序将为themelayoututilities。如果在上述语句之前创建了一些层,只要具有这些名称的层不存在,这三个层就会被创建并添加到现有层列表的末尾。但是,如果已存在具有相同名称的层,则上述语句将只创建两个新层。例如,如果layout已存在,则只会创建themeutilities,但在这种情况下,层的顺序将为layoutthemeutilities

用于命名层和匿名层的@layer块@规则

可以使用块@layer@规则创建层。如果@layer@规则后跟一个标识符和一个样式块,则该标识符用于命名层,并且此@规则中的样式将添加到该层的样式中。如果尚未存在具有指定名称的层,则会创建一个新层。如果已存在具有指定名称的层,则样式将添加到先前存在的层中。如果在使用@layer创建样式块时未指定名称,则@规则中的样式将添加到一个新的匿名层中。

在下面的示例中,我们使用了四个@layer块@规则和一个@layer语句@规则。此 CSS 按列出的顺序执行以下操作

  1. 创建一个名为layout的层
  2. 创建一个未命名的匿名层
  3. 声明一个包含三个层的列表,并只创建两个新层themeutilities,因为layout已存在
  4. 向已存在的layout层添加其他样式
  5. 创建一个第二个未命名的匿名层
css
/* file: layers1.css */

/* unlayered styles */
body {
  color: #333;
}

/* creates the first layer: `layout` */
@layer layout {
  main {
    display: grid;
  }
}

/* creates the second layer: an unnamed, anonymous layer */
@layer {
  body {
    margin: 0;
  }
}

/* creates the third and fourth layers: `theme` and `utilities` */
@layer theme, layout, utilities;

/* adds styles to the already existing `layout` layer */
@layer layout {
  main {
    color: #000;
  }
}

/* creates the fifth layer: an unnamed, anonymous layer */
@layer {
  body {
    margin: 1vw;
  }
}

在上面的 CSS 中,我们创建了五个层:layout<anonymous(01)>themeutilities<anonymous(02)> - 按此顺序 - 以及包含在body样式块中的第六个隐式未分层样式层。层的顺序是创建层的顺序,未分层样式的隐式层始终是最后一个。创建后无法更改层顺序。

我们将一些样式分配给了名为layout的层。如果命名层尚不存在,则在@layer@规则中指定名称(无论是否为层分配样式),都会创建该层;这会将层添加到现有层名称序列的末尾。如果命名层已存在,则命名块中的所有样式都会附加到先前存在的层中的样式中 - 通过重用现有层名称在块中指定样式不会创建新层。

匿名层是通过在不命名层的情况下为层分配样式来创建的。只能在创建匿名层时向未命名层添加样式。

注意:随后使用@layer且没有层名称会创建其他未命名的层;它不会将样式附加到先前存在的未命名层。

@layer@规则创建命名或未命名的层,或者如果命名层已存在,则将样式附加到该层。我们将第一个匿名层称为<anonymous(01)>,第二个称为<anonymous(02)>,这仅仅是为了我们能够解释它们。这些实际上是未命名的层。无法引用它们或向它们添加其他样式。

在层之外声明的所有样式都合并到一个隐式层中。在上面的示例代码中,第一个声明在body上设置了color: #333属性。这是在任何层之外声明的。即使未分层样式的特异性较低且在出现顺序中排在首位,普通未分层声明也优先于普通分层声明。这解释了为什么即使未分层 CSS 在代码块中首先声明,包含这些未分层样式的隐式层也具有优先级,就像它是最后声明的层一样。

@layer theme, layout, utilities;一行中,声明了一系列层,仅创建了themeutilities层;layout已在第一行创建。请注意,此声明不会更改已创建层的顺序。目前,一旦声明就无法重新排序层。

在以下交互式示例中,我们将样式分配给两个层,并在过程中创建并命名它们。因为它们已经存在,所以在第一次使用时被创建,所以在最后一行声明它们没有任何作用。

尝试移动最后一行@layer site, page;,使其成为第一行。会发生什么?

层创建和媒体查询

如果使用媒体功能查询定义层,并且媒体不匹配或不支持该功能,则不会创建该层。下面的示例显示了更改设备或浏览器的尺寸如何可能更改层顺序。在此示例中,我们仅在较宽的浏览器中创建site层。然后,我们按顺序为pagesite层分配样式。

在宽屏幕上,site层在第一行声明,这意味着site的优先级低于page。否则,site优先于page,因为它在窄屏幕上稍后声明。如果这不起作用,请尝试将媒体查询中的50em更改为10em100em

使用@import将样式表导入命名层和匿名层

@import规则允许用户将样式规则从其他样式表直接导入到 CSS 文件或<style>元素中。

在导入样式表时,@import 语句必须定义在样式表或 <style> 块中的任何 CSS 样式之前。@import 语句必须放在首位,位于任何样式之前,但可以在其前面使用一个 @layer at-rule 创建一个或多个层,而无需为这些层分配任何样式。(@import 也可以放在 @charset 规则之前。)

您可以将样式表导入到命名层、嵌套命名层或匿名层中。以下层分别将样式表导入到 components 层、components 层内的嵌套 dialog 层以及未命名的层中

css
@import url("components-lib.css") layer(components);
@import url("dialog.css") layer(components.dialog);
@import url("marketing.css") layer();

您可以将多个 CSS 文件导入到单个层中。以下声明将两个单独的文件导入到单个 social 层中

css
@import url(comments.css) layer(social);
@import url(sm-icons.css) layer(social);

您可以使用 媒体查询特性查询 根据特定条件导入样式并创建层。以下仅当浏览器支持 display: ruby 时,才将样式表导入到 international 层中,并且正在导入的文件取决于屏幕宽度。

css
@import url("ruby-narrow.css") layer(international) supports(display: ruby) and
  (width < 32rem);
@import url("ruby-wide.css") layer(international) supports(display: ruby) and
  (width >= 32rem);

注意: 没有等效于 <link> 链接样式表的方法。当您无法在样式表中使用 @layer 时,请使用 @import 将样式表导入到层中。

嵌套层叠样式表概述

嵌套层是在命名层或匿名层内的层。每个级联层,即使是匿名层,也可以包含嵌套层。导入到另一个层中的层成为该层内的嵌套层。

嵌套层的优势

嵌套层的能力使团队能够创建级联层,而不必担心其他团队是否会将其导入到层中。类似地,嵌套使您可以将第三方样式表导入到层中,而不必担心该样式表本身是否包含层。因为层可以嵌套,所以您不必担心外部和内部样式表之间存在冲突的层名称。

创建嵌套级联层

嵌套层可以使用与常规层相同的方法创建。例如,可以使用 @layer at-rule 后跟一个或多个层的名称,使用点表示法创建。多个点和层名称表示多个嵌套。

如果将一个块 @layer at-rule 嵌套在另一个块 @layer at-rule 内部,无论是否有名称,嵌套块都将成为嵌套层。类似地,当使用包含 layer 关键字或 layer() 函数的 @import 声明导入样式表时,样式将被分配到该命名或匿名层。如果 @import 语句包含层,则这些层将成为该匿名或命名层内的嵌套层。

让我们看下面的例子

css
@import url("components-lib.css") layer(components);
@import url("narrowtheme.css") layer(components.narrow);

在第一行中,我们将 components-lib.css 导入到 components 层中。如果该文件包含任何层(命名或未命名),则这些层将成为 components 层内的嵌套层。

第二行将 narrowtheme.css 导入到 narrow 层中,该层是 components 的子层。嵌套的 components.narrow 将作为 components 层内的最后一个层创建,除非 components-lib.css 已经包含一个 narrow 层,在这种情况下,narrowtheme.css 的内容将附加到 components.narrow 嵌套层。可以使用 components.<layerName> 模式将其他嵌套命名层添加到 components 层。如前所述,可以创建未命名的层,但随后无法访问它们。

让我们看另一个例子,我们 使用以下语句将 layers1.css 导入到命名层中

css
@import url(layers1.css) layer(example);

这将创建一个名为 example 的单个层,其中包含一些声明和五个嵌套层 - example.layoutexample.<anonymous(01)>example.themeexample.utilitiesexample.<anonymous(02)>

要向命名嵌套层添加样式,请使用点表示法

css
@layer example.layout {
  main {
    width: 50vw;
  }
}

根据层级顺序确定优先级

层的顺序决定了它们的优先级顺序。因此,层的顺序非常重要。与级联按来源和重要性排序的方式相同,级联按来源层和重要性对每个 CSS 声明进行排序。

常规级联层的优先级顺序

css
@import url(A.css) layer(firstLayer);
@import url(B.css) layer(secondLayer);
@import url(C.css);

以上代码创建了两个命名层(C.css 样式将附加到未分层样式的隐式层)。假设这三个文件(A.cssB.cssC.css)在其内部不包含任何其他层。以下列表显示了在这些文件内部和外部声明的样式将如何从最低(1)优先级到最高(10)优先级进行排序。

  1. firstLayer 普通样式 (A.css)
  2. secondLayer 普通样式 (B.css)
  3. 未分层普通样式 (C.css)
  4. 内联普通样式
  5. 动画样式
  6. 未分层重要样式 (C.css)
  7. secondLayer 重要样式 (B.css)
  8. firstLayer 重要样式 (A.css)
  9. 内联重要样式
  10. 过渡样式

在层内声明的普通样式具有最低优先级,并按创建层的顺序排序。第一个创建的层中的普通样式具有最低优先级,而最后一个创建的层中的普通样式在层中具有最高优先级。换句话说,如果存在任何冲突,则在 firstLayer 中声明的普通样式将被列表中任何后续样式覆盖。

接下来是层外声明的任何样式。C.css 中的样式未导入到层中,并将覆盖来自 firstLayersecondLayer 的任何冲突样式。在层外声明的样式始终优先于在层内声明的样式(重要样式除外)。

内联样式使用 style 属性 声明。以这种方式声明的普通样式将优先于在未分层和分层样式表(firstLayer – A.csssecondLayer – B.cssC.css)中找到的普通样式。

动画样式优先于所有普通样式,包括内联普通样式。

重要样式,即包含 !important 标志的属性值,优先于我们列表中之前提到的任何样式。它们按普通样式的相反顺序排序。在层外声明的任何重要样式都比在层内声明的样式优先级低。在层内找到的重要样式也按层创建顺序排序。对于重要样式,最后创建的层具有最低优先级,而第一个创建的层在声明的层中具有最高优先级。

内联重要样式再次优先于在其他地方声明的重要样式。

过渡样式具有最高优先级。当普通属性值正在过渡时,它优先于所有其他属性值声明,即使是内联重要样式;但仅在过渡期间。

在此示例中,最初使用 @layer 语句 at-rule 定义了两个层(AB),没有任何样式。层样式定义在两个 @layer 块 at-rule 中,它们出现在任何层外部声明的 h1 CSS 规则之后。

使用 style 属性在 h1 元素上添加的内联样式设置了普通 color 和重要 background-color。普通内联样式覆盖所有分层和未分层的普通样式。重要内联样式覆盖所有分层和未分层的普通和重要作者样式。作者样式无法覆盖重要内联样式。

普通 text-decoration 和重要 box-shadow 不是 style 内联样式的一部分,因此可以被覆盖。对于普通非内联样式,未分层样式优先。对于重要样式,层顺序也很重要。虽然未分层普通样式覆盖层中设置的所有普通样式,但对于重要样式,优先级顺序相反;未分层重要样式的优先级低于分层样式。

仅在层内声明的两个样式是 font-style(具有普通重要性)和 font-weight(具有 !important 标志)。对于普通样式,最后声明的 B 层覆盖先前声明的层 A 中的样式。对于普通样式,后面的层优先于前面的层。重要样式的优先级顺序相反。对于重要 font-weight 声明,第一个声明的层 A 优先于最后声明的层 B

您可以通过将第一行从 @layer A, B; 更改为 @layer B, A; 来反转层顺序。试试看。哪些样式会因此而更改,哪些样式保持不变?为什么?

层的顺序由层在 CSS 中出现的顺序设置。在我们的第一行中,我们使用 @layer 后跟层名称声明了层,而没有分配任何样式,最后以分号结尾。如果我们省略了这一行,结果将相同。为什么?我们在命名 @layer 块中按 A 然后 B 的顺序分配了样式规则。这两个层是在第一行创建的。如果没有,这些规则块将按该顺序创建它们。

我们包含第一行有两个原因:首先,以便您可以轻松地编辑该行并切换顺序;其次,因为您通常会发现预先声明层顺序是层顺序管理的最佳实践。

总结

  • 层的优先级顺序是创建层的顺序。
  • 创建后,无法更改层顺序。
  • 普通样式的层优先级是创建层的顺序。
  • 未分层普通样式优先于分层普通样式。
  • 重要样式的层优先级相反,先创建的层具有优先级。
  • 所有分层重要样式都优先于未分层重要(和普通)样式。
  • 普通内联样式优先于所有普通样式,无论是否分层。
  • 重要内联样式优先于所有其他样式,正在过渡的样式除外。
  • 作者样式无法覆盖重要内联样式(过渡除外,过渡是临时的)。

嵌套级联层的优先级顺序

嵌套层的级联优先级顺序类似于常规层的优先级顺序,但包含在层内。优先级顺序基于嵌套层创建的顺序。层中的非嵌套样式优先于嵌套普通样式,而重要样式的优先级顺序相反。嵌套层之间的特异性权重无关紧要,尽管对于嵌套层内的冲突样式,特异性权重很重要。

以下创建并向 components 层、components.narrow 嵌套层和 components.wide 嵌套层添加样式

css
div {
  background-color: wheat;
  color: pink !important;
}

@layer components {
  div {
    background-color: yellow;
    border: 1rem dashed red;
    color: orange !important;
  }
}

@layer components.narrow {
  div {
    background-color: skyblue;
    border: 1rem dashed blue;
    color: purple !important;
    border-radius: 50%;
  }
}

@layer components.wide {
  div {
    background-color: limegreen;
    border: 1rem dashed green;
    color: seagreen !important;
    border-radius: 20%;
  }
}

以下是使用的属性以及每个声明应用的原因的摘要

  • background-color:因为未分层普通样式优先于分层普通样式,所以 wheat 颜色获胜。
  • border:因为在层内,非嵌套样式优先于普通嵌套样式,所以 red 颜色获胜。
  • color:对于重要样式,分层样式优先于未分层样式,并且在先前声明的层中的重要样式优先于后续声明的层中的重要样式。在此示例中,嵌套层创建的顺序是 components.narrow,然后是 components.wide,因此 components.narrow 中的重要样式优先于 components.wide 中的重要样式,这意味着 purple 颜色获胜。
  • border-radius:该属性仅在嵌套层中设置,因此按声明顺序 20% 半径获胜。

测试你的技能!

您已阅读完本文,但您能记住最重要的信息吗?在继续之前,您可以找到一些进一步的测试来验证您是否保留了这些信息——请参阅 测试您的技能:级联,任务 2

总结

如果您理解了本文的大部分内容,那么恭喜您——您现在已经熟悉了 CSS 级联层的根本机制。接下来,我们将详细了解 盒模型