级联、特异性和继承

本课程的目的是加深你对 CSS 一些最基本概念(级联、特异性和继承)的理解,这些概念控制着 CSS 如何应用于 HTML 以及如何解决样式声明之间的冲突。

¥The aim of this lesson is to develop your understanding of some of the most fundamental concepts of CSS — the cascade, specificity, and inheritance — which control how CSS is applied to HTML and how conflicts between style declarations are resolved.

虽然完成本课程可能看起来不太相关,并且比课程的其他部分更具学术性,但对这些概念的理解将使你在以后免受很多痛苦!我们鼓励你仔细阅读本节,并在继续之前检查你是否理解这些概念。

¥While working through this lesson may seem less relevant immediately and a little more academic than some other parts of the course, an understanding of these concepts will save you from a lot of pain later on! We encourage you to work through this section carefully and check that you understand the concepts before moving on.

先决条件: 基本软件已安装处理文件 的基础知识、HTML 基础知识(学习 HTML 简介)以及 CSS 工作原理的想法(学习 CSS 第一步)。
目标: 了解级联和特殊性,以及继承在 CSS 中的工作原理。

规则冲突

¥Conflicting rules

CSS 代表级联样式表,理解第一个词级联非常重要 - 级联的行为方式是理解 CSS 的关键。

¥CSS stands for Cascading Style Sheets, and that first word cascading is incredibly important to understand — the way that the cascade behaves is key to understanding CSS.

在某些时候,你将从事一个项目,并且你会发现你认为应该应用于某个元素的 CSS 不起作用。通常,问题在于你创建两个规则,将同一属性的不同值应用于同一元素。级联 和密切相关的 specificity 概念是在发生此类冲突时控制适用哪条规则的机制。设计元素样式的规则可能不是你所期望的,因此你需要了解这些机制是如何工作的。

¥At some point, you will be working on a project and you will find that the CSS you thought should be applied to an element is not working. Often, the problem is that you create two rules that apply different values of the same property to the same element. Cascade and the closely-related concept of specificity are mechanisms that control which rule applies when there is such a conflict. The rule that's styling your element may not be the one you expect, so you need to understand how these mechanisms work.

这里同样重要的是 inheritance 的概念,这意味着默认情况下某些 CSS 属性会继承当前元素的父元素上设置的值,而有些则不会。这也可能导致一些你可能意想不到的行为。

¥Also significant here is the concept of inheritance, which means that some CSS properties by default inherit values set on the current element's parent element and some don't. This can also cause some behavior that you might not expect.

让我们首先快速浏览一下我们正在处理的关键事物,然后我们将依次查看每个事物并了解它们如何彼此交互以及你的 CSS 交互。这些似乎是一组难以理解的概念。随着你更多地练习编写 CSS,它的工作方式对你来说将会变得更加明显。

¥Let's start by taking a quick look at the key things we are dealing with, then we'll look at each in turn and see how they interact with each other and your CSS. These can seem like a tricky set of concepts to understand. As you get more practice writing CSS, the way it works will become more obvious to you.

级联

¥Cascade

样式表 cascade — 在非常简单的层面上,这意味着 CSS 规则的起源、级联层和顺序很重要。当应用来自同一级联层的两个规则并且两者具有相同的特异性时,将使用样式表中最后定义的那个规则。

¥Stylesheets cascade — at a very simple level, this means that the origin, the cascade layer, and the order of CSS rules matter. When two rules from the same cascade layer apply and both have equal specificity, the one that is defined last in the stylesheet is the one that will be used.

在下面的示例中,我们有两个可以应用于 <h1> 元素的规则。<h1> 内容最终被染成蓝色。这是因为这两个规则都来自同一源,具有相同的元素选择器,因此具有相同的特异性,但源顺序中的最后一个获胜。

¥In the below example, we have two rules that could apply to the <h1> element. The <h1> content ends up being colored blue. This is because both the rules are from the same source, have an identical element selector, and therefore, carry the same specificity, but the last one in the source order wins.

特异性

¥Specificity

特异性 是浏览器用来决定将哪个属性值应用于元素的算法。如果多个样式块具有不同的选择器,这些选择器使用不同的值配置相同的属性并针对相同的元素,则特异性决定应用于该元素的属性值。特异性基本上是衡量选择器选择的具体程度的指标:

¥Specificity is the algorithm that the browser uses to decide which property value is applied to an element. If multiple style blocks have different selectors that configure the same property with different values and target the same element, specificity decides the property value that gets applied to the element. Specificity is basically a measure of how specific a selector's selection will be:

  • 元素选择器不太具体;它将选择页面上出现的该类型的所有元素,因此它的权重较小。伪元素选择器与常规元素选择器具有相同的特异性。
  • 类选择器更加具体;它只会选择页面上具有特定 class 属性值的元素,因此它具有更大的权重。属性选择器和伪类与类具有相同的权重。

下面,我们再次有两个可以应用于 <h1> 元素的规则。下面的 <h1> 内容最终被涂成红色,因为类选择器 main-heading 赋予其规则更高的特异性。因此,即使具有 <h1> 元素选择器的规则在源顺序中显示得更靠下,也会应用使用类选择器定义的具有更高特异性的规则。

¥Below, we again have two rules that could apply to the <h1> element. The <h1> content below ends up being colored red because the class selector main-heading gives its rule a higher specificity. So even though the rule with the <h1> element selector appears further down in the source order, the one with the higher specificity, defined using the class selector, will be applied.

稍后我们将解释特异性算法。

¥We'll explain the specificity algorithm later on.

遗产

¥Inheritance

在这种情况下还需要理解继承 - 父元素上设置的一些 CSS 属性值会被其子元素继承,而有些则不会。

¥Inheritance also needs to be understood in this context — some CSS property values set on parent elements are inherited by their child elements, and some aren't.

例如,如果你在元素上设置 colorfont-family,则其中的每个元素也将使用该颜色和字体设置样式,除非你直接向它们应用了不同的颜色和字体值。

¥For example, if you set a color and font-family on an element, every element inside it will also be styled with that color and font, unless you've applied different color and font values directly to them.

有些属性不会继承 - 例如,如果你在某个元素上设置 width 为 50%,则其所有后代的宽度都不会达到其父级宽度的 50%。如果是这样的话,CSS 用起来就很麻烦了!

¥Some properties do not inherit — for example, if you set a width of 50% on an element, all of its descendants do not get a width of 50% of their parent's width. If this was the case, CSS would be very frustrating to use!

注意:在 MDN CSS 属性参考页面上,你可以找到一个名为 "正式定义" 的技术信息框,其中列出了有关该属性的许多数据点,包括它是否是继承的。以 颜色属性正式定义部分 为例。

¥Note: On MDN CSS property reference pages, you can find a technical information box called "Formal definition", which lists a number of data points about that property, including whether it is inherited or not. See the color property Formal definition section as an example.

了解这些概念如何协同工作

¥Understanding how the concepts work together

这三个概念(级联、特异性和继承)共同控制哪个 CSS 应用于哪个元素。在下面的部分中,我们将了解它们如何协同工作。它有时看起来有点复杂,但是随着你对 CSS 的了解越来越多,你会开始记住它们,如果你忘记了,你可以随时查找详细信息!即使是经验丰富的开发者也不会记住所有细节。

¥These three concepts (cascade, specificity, and inheritance) together control which CSS applies to what element. In the sections below, we'll see how they work together. It can sometimes seem a little bit complicated, but you will start to remember them as you get more experienced with CSS, and you can always look up the details if you forget! Even experienced developers don't remember all the details.

以下视频展示了如何使用 Firefox DevTools 检查页面的级联、特异性等:

¥The following video shows how you can use the Firefox DevTools to inspect a page's cascade, specificity, and more:

了解继承

¥Understanding inheritance

我们将从继承开始。在下面的示例中,我们有一个 <ul> 元素,其中嵌套了两层无序列表。我们为外部 <ul> 指定了边框、填充和字体颜色。

¥We'll start with inheritance. In the example below, we have a <ul> element with two levels of unordered lists nested inside it. We have given the outer <ul> a border, padding, and font color.

color 属性是继承属性。因此,color 属性值应用于直接子级,也应用于间接子级 - 直接子级 <li> 和第一个嵌套列表内的子级。然后,我们将类 special 添加到第二个嵌套列表中,并为其应用不同的颜色。然后,它会通过其子级继承下来。

¥The color property is an inherited property. So, the color property value is applied to the direct children and also to the indirect children — the immediate child <li>s and those inside the first nested list. We have then added the class special to the second nested list and applied a different color to it. This then inherits down through its children.

诸如 width(如前所述)、marginpaddingborder 之类的属性不是继承属性。如果在此列表示例中的子级继承边框,则每个列表和列表项都将获得边框 - 可能不是我们想要的效果!

¥Properties like width (as mentioned earlier), margin, padding, and border are not inherited properties. If a border were to be inherited by the children in this list example, every single list and list item would gain a border — probably not an effect we would ever want!

虽然每个 CSS 属性页都会列出该属性是否是继承的,但如果你知道该属性值将样式化到哪个方面,你通常可以直观地猜测到相同的内容。

¥Though every CSS property page lists whether or not the property is inherited, you can often guess the same intuitively if you know what aspect the property value will style.

控制继承

¥Controlling inheritance

CSS 提供了五个特殊的通用属性值来控制继承。每个 CSS 属性都接受这些值。

¥CSS provides five special universal property values for controlling inheritance. Every CSS property accepts these values.

inherit

将应用于所选元素的属性值设置为与其父元素的属性值相同。实际上,这个 "开启继承"。

initial

将应用于选定元素的属性值设置为该属性的 初始值

revert

将应用于选定元素的属性值重置为浏览器的默认样式,而不是应用于该属性的默认样式。在许多情况下,该值的作用类似于 unset

revert-layer

将应用于所选元素的属性值重置为先前 级联层 中建立的值。

unset

将属性重置为其自然值,这意味着如果该属性是自然继承的,则它的行为类似于 inherit,否则它的行为类似于 initial

注意:有关这些内容及其工作原理的更多信息,请参阅 产地类型

¥Note: See Origin types for more information on each of these and how they work.

我们可以查看链接列表并探索普世价值如何发挥作用。下面的实时示例允许你使用 CSS 并查看进行更改时会发生什么。玩代码确实是更好地理解 HTML 和 CSS 的最佳方法。

¥We can look at a list of links and explore how universal values work. The live example below allows you to play with the CSS and see what happens when you make changes. Playing with code really is the best way to better understand HTML and CSS.

例如:

¥For example:

  1. 第二个列表项应用了 my-class-1 类。这会将嵌套在其中的 <a> 元素的颜色设置为 inherit。如果删除规则,它如何改变链接的颜色?
  2. 你知道为什么第三个和第四个链接是这样的颜色吗?第三个链接设置为 initial,这意味着它使用属性的初始值(在本例中为黑色),而不是浏览器默认的链接值(蓝色)。第四个设置为 unset,这意味着链接文本使用父元素的颜色,绿色。
  3. 如果你为 <a> 元素定义新颜色(例如 a { color: red; }),哪个链接会改变颜色?
  4. 阅读完有关重置所有属性的下一节后,返回并将 color 属性更改为 all。请注意第二个链接如何位于新行并带有项目符号。你认为哪些属性是遗传的?

重置所有属性值

¥Resetting all property values

CSS 速记属性 all 可用于将这些继承值之一一次性应用于(几乎)所有属性。其值可以是任何一个继承值(inheritinitialrevertrevert-layerunset)。这是撤消对样式所做的更改的便捷方法,以便你可以在开始新的更改之前返回到已知的起点。

¥The CSS shorthand property all can be used to apply one of these inheritance values to (almost) all properties at once. Its value can be any one of the inheritance values (inherit, initial, revert, revert-layer, or unset). It's a convenient way to undo changes made to styles so that you can get back to a known starting point before beginning new changes.

在下面的示例中,我们有两个块引号。第一个将样式应用于块引用元素本身。第二个有一个应用于块引用的类,它将 all 的值设置为 unset

¥In the below example, we have two blockquotes. The first has styling applied to the blockquote element itself. The second has a class applied to the blockquote, which sets the value of all to unset.

尝试将 all 的值设置为其他一些可用值并观察有何差异。

¥Try setting the value of all to some of the other available values and observe what the difference is.

了解级联

¥Understanding the cascade

我们现在明白,继承是嵌套在 HTML 结构深处的段落与应用于正文的 CSS 颜色相同的原因。从入门课程中,我们了解了如何更改应用于文档中任何位置的 CSS - 无论是通过将 CSS 分配给元素还是通过创建类。现在,我们将了解当多个样式块将相同的属性(但具有不同的值)应用于同一元素时,级联如何定义应用哪些 CSS 规则。

¥We now understand that inheritance is why a paragraph nested deep in the structure of your HTML is the same color as the CSS applied to the body. From the introductory lessons, we have an understanding of how to change the CSS applied to something at any point in the document — whether by assigning CSS to an element or by creating a class. We will now look at how cascade defines which CSS rules apply when more than one style block apply the same property, but with different values, to the same element.

需要考虑三个因素,此处按重要性递增顺序列出。后来的推翻了之前的:

¥There are three factors to consider, listed here in increasing order of importance. Later ones overrule earlier ones:

  1. 来源订单
  2. 特异性
  3. 重要性

我们将通过这些来了解浏览器如何准确地确定应该应用哪些 CSS。

¥We will look at these to see how browsers figure out exactly what CSS should be applied.

来源订单

¥Source order

我们已经了解了源顺序对于级联的重要性。如果你有多个规则,并且所有规则的权重完全相同,则 CSS 中最后的规则将获胜。你可以将其视为:较接近元素本身的规则会覆盖较早的规则,直到最后一个获胜并开始设置元素的样式。

¥We have already seen how source order matters to the cascade. If you have more than one rule, all of which have exactly the same weight, then the one that comes last in the CSS will win. You can think of this as: the rule that is nearer the element itself overwrites the earlier ones until the last one wins and gets to style the element.

仅当规则的特异性权重相同时,源顺序才重要,所以让我们看看特异性:

¥Source order only matters when the specificity weight of the rules is the same, so let's look at specificity:

特异性

¥Specificity

你经常会遇到这样的情况:你知道样式表中的规则稍后出现,但应用了较早的冲突规则。发生这种情况是因为早期的规则具有更高的特异性 - 它更具体,因此被浏览器选择为应该设置元素样式的规则。

¥You will often run into a situation where you know that a rule comes later in the stylesheet, but an earlier, conflicting rule is applied. This happens because the earlier rule has a higher specificity — it is more specific, and therefore, is being chosen by the browser as the one that should style the element.

正如我们在本课前面看到的,类选择器比元素选择器具有更大的权重,因此类样式块中定义的属性将覆盖元素样式块中定义的属性。

¥As we saw earlier in this lesson, a class selector has more weight than an element selector, so the properties defined in the class style block will override those defined in the element style block.

这里需要注意的是,尽管我们正在考虑选择器以及应用于它们选择的文本或组件的规则,但覆盖的并不是整个规则,而是在多个位置声明的属性。

¥Something to note here is that although we are thinking about selectors and the rules that are applied to the text or component they select, it isn't the entire rule that is overwritten, only the properties that are declared in multiple places.

此行为有助于避免 CSS 中的重复。常见的做法是为基本元素定义通用样式,然后为不同的元素创建类。例如,在下面的样式表中,我们为 2 级标题定义了通用样式,然后创建了一些仅更改部分属性和值的类。最初定义的值应用于所有标题,然后更具体的值应用于具有类别的标题。

¥This behavior helps avoid repetition in your CSS. A common practice is to define generic styles for the basic elements, and then create classes for those that are different. For example, in the stylesheet below, we have defined generic styles for level 2 headings, and then created some classes that change only some of the properties and values. The values defined initially are applied to all headings, then the more specific values are applied to the headings with the classes.

现在让我们看看浏览器如何计算特异性。我们已经知道元素选择器的特异性较低,并且可以被类覆盖。本质上,不同类型的选择器都会获得一个分数,将这些值相加就可以得到该特定选择器的权重,然后可以根据其他潜在的匹配进行评估。

¥Let's now have a look at how the browser will calculate specificity. We already know that an element selector has low specificity and can be overwritten by a class. Essentially a value in points is awarded to different types of selectors, and adding these up gives you the weight of that particular selector, which can then be assessed against other potential matches.

选择器的特异性程度是使用三个不同的值(或组件)来衡量的,可以将其视为百位、十位和个位中的 ID、CLASS 和 ELEMENT 列:

¥The amount of specificity a selector has is measured using three different values (or components), which can be thought of as ID, CLASS, and ELEMENT columns in the hundreds, tens, and ones place:

  • 身份标识:对于整个选择器中包含的每个 ID 选择器,在此列中得一分。
  • 课程:对于整个选择器中包含的每个类选择器、属性选择器或伪类,在此列中得一分。
  • 要素:对于整个选择器中包含的每个元素选择器或伪元素,在此列中得一分。

注意:通用选择器 (*)、combinators (+>~、'') 和特异性调整选择器 (:where()) 及其参数对特异性没有影响。

¥Note: The universal selector (*), combinators (+, >, ~, ' '), and specificity adjustment selector (:where()) along with its parameters, have no effect on specificity.

否定 (:not())、关系选择器 (:has())、匹配任意 (:is()) 伪类和 CSS 嵌套 本身不会增加特异性,但它们的参数或嵌套规则会增加特异性。每个对特异性算法贡献的特异性权重是权重最大的参数或嵌套规则中选择器的特异性权重。

¥The negation (:not()), relational selector (:has()), the matches-any (:is()) pseudo-classes, and CSS nesting themselves don't add to specificity, but their parameters or nested rules do. The specificity weight that each contributes to the specificity algorithm is the specificity weight of the selector in the parameter or nested rule with the greatest weight.

下表显示了一些单独的示例,以帮助你了解情况。尝试仔细阅读这些内容,并确保你理解为什么它们具有我们赋予它们的特殊性。我们尚未详细介绍选择器,但你可以在 MDN 选择器参考 上找到每个选择器的详细信息。

¥The following table shows a few isolated examples to get you in the mood. Try going through these, and make sure you understand why they have the specificity that we have given them. We've not covered selectors in detail yet, but you can find details of each selector on the MDN selectors reference.

选择器 身份标识 元素 总特异性
h1 0 0 1 0-0-1
h1 + p::first-letter 0 0 3 0-0-3
li > a[href*="en-US"] > .inline-warning 0 2 2 0-2-2
#identifier 1 0 0 1-0-0
button:not(#mainBtn, .cta) 1 0 1 1-0-1

在继续之前,让我们看一个实际示例。

¥Before we move on, let's look at an example in action.

那么这是怎么回事呢?首先,我们只对此示例的前七个规则感兴趣,并且你会注意到,我们已在每个规则之前的注释中包含了它们的特异性值。

¥So what's going on here? First of all, we are only interested in the first seven rules of this example, and as you'll notice, we have included their specificity values in a comment before each one.

  • 前两个选择器正在竞争链接背景颜色的样式。第二个获胜并将背景颜色设置为蓝色,因为它在链中具有额外的 ID 选择器:其特异性为 2-0-1 与 1-0-1。
  • 选择器 3 和 4 正在竞争链接文本颜色的样式。第二个获胜并使文本变为白色,因为尽管它少了一个元素选择器,但缺少的选择器被替换为类选择器,该类选择器比无穷大元素选择器具有更大的权重。获胜的具体情况是 1-1-3 与 1-0-4。
  • 选择器 5-7 正在竞争悬停时链接边框的样式。选择器 6 明显输给了选择器 5,特异性为 0-2-3 vs. 0-2-4;它在链中少了一个元素选择器。然而,选择器 7 击败了选择器 5 和 6,因为它在链中具有与选择器 5 相同数量的子选择器,但其中一个元素已被替换为类选择器。因此获胜的特殊性是 0-3-3 与 0-2-3 和 0-2-4。

注意:每个选择器类型都有其自己的特异性级别,不能被具有较低特异性级别的选择器覆盖。例如,一百万个类选择器组合起来将无法覆盖一个 id 选择器的特异性。

¥Note: Each selector type has its own level of specificity that cannot be overwritten by selectors with a lower specificity level. For example, a million class selectors combined would not be able to overwrite the specificity of one id selector.

评估特异性的最佳方法是从最高的特异性水平开始单独评分,并在必要时转向最低的水平。仅当特异性列中的选择器分数之间存在平局时,你才需要评估下一列;否则,你可以忽略较低特异性的选择器,因为它们永远无法覆盖较高特异性的选择器。

¥The best way to evaluate specificity is to score the specificity levels individually starting from the highest and moving on to the lowest when necessary. Only when there is a tie between selector scores within a specificity column do you need to evaluate the next column down; otherwise, you can disregard the lower specificity selectors since they can never overwrite the higher specificity selectors.

内联样式

¥Inline styles

内联样式(即 style 属性内的样式声明)优先于所有普通样式,无论其特殊性如何。此类声明没有选择器,但其特异性可以解释为 1-0-0-0;无论选择器中有多少个 ID,它始终高于任何其他特异性权重。

¥Inline styles, that is, the style declaration inside a style attribute, take precedence over all normal styles, no matter the specificity. Such declarations don't have selectors, but their specificity can be construed as 1-0-0-0; always more than any other specificity weight no matter how many IDs are in the selectors.

!important

有一个特殊的 CSS 片段,你可以使用它来推翻所有上述计算,甚至是内联样式 - !important 标志。但是,使用时应该非常小心。该标志用于使单个属性和值对成为最具体的规则,从而覆盖级联的正常规则,包括正常的内联样式。

¥There is a special piece of CSS that you can use to overrule all of the above calculations, even inline styles - the !important flag. However, you should be very careful while using it. This flag is used to make an individual property and value pair the most specific rule, thereby overriding the normal rules of the cascade, including normal inline styles.

注意:了解 !important 标志的存在很有用,这样当你在其他人的代码中遇到它时就知道它是什么。但是,我们强烈建议你不要使用它,除非绝对必要。!important 标志改变了级联正常工作的方式,因此它会使调试 CSS 问题变得非常困难,尤其是在大型样式表中。

¥Note: It is useful to know that the !important flag exists so that you know what it is when you come across it in other people's code. However, we strongly recommend that you never use it unless you absolutely have to. The !important flag changes the way the cascade normally works, so it can make debugging CSS problems really hard to work out, especially in a large stylesheet.

看一下这个示例,其中有两个段落,其中一个有 ID。

¥Take a look at this example where we have two paragraphs, one of which has an ID.

让我们来看看发生了什么 - 尝试删除一些属性,看看如果你发现很难理解会发生什么:

¥Let's walk through this to see what's happening — try removing some of the properties to see what happens if you are finding it hard to understand:

  1. 你将看到第三条规则的 colorpadding 值已应用,但 background-color 尚未应用。为什么?实际上,这三个规则肯定都适用,因为源顺序中后面的规则通常会覆盖前面的规则。
  2. 然而,上面的规则获胜,因为类选择器比元素选择器具有更高的特异性。
  3. 两个元素都有 classbetter,但第二个元素也有 idwinning。由于 ID 比类具有更高的特异性(页面上只能有一个具有唯一 ID 的元素,但许多具有相同类的元素 — ID 选择器的目标非常具体),因此红色背景颜色和 1px 黑色边框应该应用于第二个元素,第一个元素获得灰色背景颜色,并且没有边框,如类所指定的。
  4. 第二个元素确实获得了红色背景颜色,但没有边框。为什么?因为第二条规则中有 !important 标志。在 border: none 之后添加 !important 标志意味着该声明将胜过上一条规则中的 border 值,即使 ID 选择器具有更高的特异性。

注意:覆盖重要声明的唯一方法是在源顺序后面包含另一个具有相同特异性的重要声明,或者具有更高特异性的重要声明,或者在前面的级联层中包含一个重要声明(我们还没有涵盖级联层) )。

¥Note: The only way to override an important declaration is to include another important declaration with the same specificity later in the source order, or one with higher specificity, or to include an important declaration in a prior cascade layer (we haven't covered cascade layers yet).

你可能必须使用 !important 标志的一种情况是,当你在 CMS 上工作时,你无法编辑核心 CSS 模块,并且你确实想要覆盖内联样式或无法覆盖的重要声明 以任何其他方式。但实际上,如果可以避免,就不要使用它。

¥One situation in which you may have to use the !important flag is when you are working on a CMS where you can't edit the core CSS modules, and you really want to override an inline style or an important declaration that can't be overridden in any other way. But really, don't use it if you can avoid it.

CSS 定位的效果

¥The effect of CSS location

最后,需要注意的是,CSS 声明的优先级取决于指定的样式表和级联层。

¥Finally, it is important to note that the precedence of a CSS declaration depends on what stylesheet and cascade layer it is specified in.

用户可以设置自定义样式表来覆盖开发者的样式。例如,视力受损的用户可能希望将他们访问的所有网页上的字体大小设置为正常大小的两倍,以便于阅读。

¥It is possible for users to set custom stylesheets to override the developer's styles. For example, a visually impaired user might want to set the font size on all web pages they visit to be double the normal size to allow for easier reading.

还可以在级联层中声明开发者样式:你可以使非分层样式覆盖层中声明的样式,也可以使后面层中声明的样式覆盖早期声明层中的样式。例如,作为开发者,你可能无法编辑第三方样式表,但你可以将外部样式表导入到级联层中,以便所有样式轻松覆盖导入的样式,而无需担心第三方选择器的特殊性。

¥It is also possible to declare developer styles in cascade layers: you can make non-layered styles override styles declared in layers or you can make styles declared in later layers override styles from earlier declared layers. For example, as a developer you may not be able to edit a third-party stylesheet, but you can import the external stylesheet into a cascade layer so that all of your styles easily override the imported styles without worrying about third-party selector specificity.

重写声明的顺序

¥Order of overriding declarations

冲突的声明将按以下顺序应用,后面的声明覆盖前面的声明:

¥Conflicting declarations will be applied in the following order, with later ones overriding earlier ones:

  1. 用户代理样式表中的声明(例如,浏览器的默认样式,在未设置其他样式时使用)。
  2. 用户样式表中的普通声明(用户设置的自定义样式)。
  3. 作者样式表中的正常声明(这些是我们 Web 开发者设置的样式)。
  4. 作者样式表中的重要声明。
  5. 用户样式表中的重要声明。
  6. 用户代理样式表中的重要声明。

注意:对于标有 !important 的样式,优先顺序是相反的。Web 开发者的样式表覆盖用户样式表是有意义的,因此设计可以保持预期的效果;然而,有时用户有充分的理由覆盖 Web 开发者样式,如上所述,这可以通过在规则中使用 !important 来实现。

¥Note: The order of precedence is inverted for styles flagged with !important. It makes sense for web developers' stylesheets to override user stylesheets, so the design can be kept as intended; however, sometimes users have good reasons to override web developer styles, as mentioned above, and this can be achieved by using !important in their rules.

级联层顺序

¥Order of cascade layers

尽管 级联层 是一个高级主题,并且你可能不会立即使用此功能,但了解层如何级联也很重要。

¥Even though cascade layers is an advanced topic and you might not use this feature right away, it's important to understand how layers cascade.

当你在级联层中声明 CSS 时,优先顺序由声明层的顺序决定。在任何层外部声明的 CSS 样式都会按照声明这些样式的顺序组合在一起,形成一个未命名的层,就好像它是最后声明的层一样。对于竞争的普通(不重要)样式,后面的图层优先于前面定义的图层。然而,对于标记为 !important 的样式,顺序是相反的,早期层中的重要样式优先于后续层中或任何层外部声明的重要样式。内联样式优先于所有作者样式,无论层如何。

¥When you declare CSS in cascade layers, the order of precedence is determined by the order in which the layers are declared. CSS styles declared outside of any layer are combined together, in the order in which those styles are declared, into an unnamed layer, as if it were the last declared layer. With competing normal (not important) styles, later layers take precedence over earlier defined layers. For styles flagged with !important, however, the order is reversed, with important styles in earlier layers taking precedence over important styles declared in subsequent layers or outside of any layer. Inline styles take precedence over all author styles, no matter the layer.

当不同层中有多个样式块为单个元素上的属性提供竞争值时,声明层的顺序决定了优先级。层之间的特异性并不重要,但单层内的特异性仍然很重要。

¥When you have multiple style blocks in different layers providing competing values for a property on a single element, the order in which the layers are declared determines the precedence. Specificity between layers doesn't matter, but specificity within a single layer still does.

让我们讨论上面示例中的一些内容,以了解发生了什么。已按顺序声明了两个层:firstLayersecondLayer。尽管 secondLayer 中的特异性最高,但未使用该声明中的任何属性。为什么?因为无论特殊性如何,非分层普通样式都优先于分层普通样式,并且无论特殊性如何,重要的分层样式都优先于后面层中声明的重要样式。

¥Let's discuss a few things from the above example to understand what's happening. Two layers have been declared, firstLayer and secondLayer, in that order. Even though the specificity in secondLayer is the highest, no properties from that declaration are used. Why? Because non-layered normal styles take precedence over layered normal styles, no matter the specificity, and important layered styles take precedence over important styles declared in later layers, again, no matter the specificity.

如果将本例中 CSS 的第一行更改为 @layer secondLayer, firstLayer;,则会更改图层声明顺序,并且 firstLayer 中的所有重要样式都将更改为 secondLayer 中各自的值。

¥If you change the first line of CSS in this example to read @layer secondLayer, firstLayer;, you will change the layer declaration order, and all the important styles from firstLayer will be changed to their respective values in secondLayer.

范围邻近性

¥Scoping proximity

另一个你可能不会立即使用但将来可能需要了解的高级主题是 @scope。这是一个 at-rule,使你能够创建仅适用于页面上 HTML 的特定子部分的规则块。例如,你可以指定仅适用于嵌套在具有 feature 类的元素内的 <img> 元素的样式:

¥Another advanced topic that you might not use right away but may need to understand in the future is @scope. This is an at-rule that enables you to create a block of rules that will only apply to a specific subsection of the HTML on your page. For example, you can specify styles that will only apply to <img> elements when they're nested inside elements that have a feature class:

css
@scope (.feature) {
  img {
    border: 2px solid black;
    display: block;
  }
}

范围邻近性是解决范围元素之间冲突的机制。作用域邻近性指出,当两个作用域具有冲突的样式时,从 DOM 树层次结构到作用域根的跳跃次数最少的样式获胜。有关更多详细信息和示例,请参阅 @scope 冲突如何解决

¥Scoping proximity is the mechanism that resolves conflicts between scoped elements. Scoping proximity states that when two scopes have conflicting styles, the style with the smallest number of hops up the DOM tree hierarchy to the scope root wins. See How @scope conflicts are resolved for more details and an example.

注意:范围邻近性会否决源顺序,但其本身会被其他更高优先级的标准(例如 importancelayersspecificity)所覆盖。

¥Note: Scoping proximity overrules source order but is itself overridden by other, higher-priority criteria such as importance, layers, and specificity.

测试你的技能!

¥Test your skills!

你已读完本文,但你还记得最重要的信息吗?在继续之前,你可以找到一些进一步的测试来验证你是否已保留此信息 - 请参阅 测试你的技能:瀑布

¥You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: The Cascade.

概括

¥Summary

如果你理解了本文的大部分内容,那么做得很好 — 你已经开始熟悉 CSS 的基原生制。接下来,我们将深入了解 级联层

¥If you understood most of this article, then well done — you've started getting familiar with the fundamental mechanics of CSS. Next up, we'll take a deeper look at Cascade Layers.

如果你没有完全理解级联、特异性和继承,请不要担心!这绝对是我们在课程中迄今为止介绍过的最复杂的事情,即使是专业的 Web 开发者有时也会觉得棘手。我们建议你在继续学习本课程时多次返回本文,并不断思考。

¥If you didn't fully understand the cascade, specificity, and inheritance, then don't worry! This is definitely the most complicated thing we've covered so far in the course and is something that even professional web developers sometimes find tricky. We'd advise that you return to this article a few times as you continue through the course, and keep thinking about it.

如果你开始遇到样式未按预期应用的奇怪问题,请返回此处。这可能是一个特殊性问题。

¥Refer back here if you start to come across strange issues with styles not applying as expected. It could be a specificity issue.