Cascade and inheritance

 

本课程的目的是加深您对CSS的一些最基本概念(级联,特异性和继承)的理解,这些概念控制CSS如何应用于HTML以及如何解决冲突.

与本课程的其他部分相比,本课程的学习似乎没有那么直接的相关性,而且学术性更高,但是对这些内容的理解将为您以后减轻很多痛苦! 我们鼓励您仔细阅读本节,并在继续进行之前检查您是否了解这些概念.

Prerequisites: 基本的计算机知识, 已安装的基本软件使用文件的基本知识,HTML基础(研究HTML简介 )以及CSS的工作原理(研究CSS第一步) .
Objective: 了解级联和特定性,以及CSS如何继承.

Conflicting rules

CSS代表Cascading Style Sheets层叠样式表) ,而第一个单词的层叠对于理解它非常重要-级联的行为方式是理解CSS的关键.

有时,您将在一个项目上工作,并且发现您认为应该应用于元素的CSS无法正常工作. 通常问题是您创建了两个规则,它们可能适用于同一元素. 级联和密切相关的特异性概念是控制发生此类冲突时应用哪个规则的机制. 哪个元素在样式上可能不是您所期望的,因此您需要了解这些机制的工作方式.

继承的概念在这里也很重要,这意味着默认情况下,某些CSS属性会继承在当前元素的父元素上设置的值,而有些则不会. 这也可能导致某些您可能无法预期的行为.

让我们开始快速浏览一下我们正在处理的关键事物,然后我们依次研究它们,看看它们如何相互影响以及与CSS的相互作用. 这似乎是一组难以理解的棘手概念. 但是,随着您越来越多地编写CSS练习,它的工作方式将对您变得更加明显.

The cascade

样式表级联 -在非常简单的级别上,这意味着CSS规则的顺序很重要; 当应用两个具有相同特异性的规则时,将在CSS中排在最后的那个将被使用.

在下面的示例中,我们有两个适用于h1规则. h1最终变为蓝色-这些规则具有相同的选择器,因此具有相同的特异性,因此源顺序中的最后一个将获胜.

 

Specificity

如果多个规则具有不同的选择器,但浏览器如何决定哪个规则适用,但是仍然可以应用于同一元素,则是特殊性. 基本上,这是对选择器选择的具体程度的一种度量:

  • An element selector is less specific — it will select all elements of that type that appear on a page — so will get a lower score.
  • 类选择器更具体-它只会选择页面上具有特定class属性值的元素-因此得分会更高.

时间示例! 下面我们再次有两个规则可以适用于h1 . 下方的h1最终变为红色-类选择器为其规则赋予了更高的特异性,因此即使带有元素选择器的规则在源顺序中排在了更下方,也将应用该规则.

 

我们将在以后解释特异性评分和其他类似的事情.

Inheritance

在这种情况下,也需要了解继承-在父元素上设置的某些CSS属性值是由其子元素继承的,而有些则不是.

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

 

某些属性不会继承-例如,如果您在元素上设置50%的width ,则其所有后代的宽度都不会达到其父代宽度的50%. 如果真是这样,CSS将会非常令人沮丧!

注意 :在MDN CSS属性参考页面上,您通常可以在规格部分的底部找到技术信息框,其中列出了有关该属性的许多数据点,包括是否继承. 例如,请参阅颜色属性"规格"部分 .

Understanding how the concepts work together

这三个概念共同控制哪个CSS适用于哪个元素; 在以下各节中,我们将看到它们如何协同工作. 有时似乎有些复杂,但是随着您对CSS的使用越来越多,您将开始记住它们,如果忘记了,您总是可以查找细节! 即使是经验丰富的开发人员也不会记住所有细节.

Understanding inheritance

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

颜色适用于直接子代,也适用于间接子代-直接子代<li>以及第一个嵌套列表内的子代. 然后,我们在第二个嵌套列表中添加了一个special类,并为其应用了不同的颜色. 然后,通过其子项继承下来.

 

宽度(如上所述),边距,填充和边框等内容不会继承. 如果要由我们列表的子代继承边框,则每个列表和列表项都将具有边框-可能不是我们想要的效果!

哪些属性默认情况下是继承的,哪些不是默认情况下的继承.

Controlling inheritance

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

inherit
将应用于选定元素的属性值设置为其父元素的属性值. 实际上,这是"继承".
initial
将应用于所选元素的属性值设置为与浏览器默认样式表中对该元素上的该属性设置的值相同. 如果浏览器的默认样式表未设置任何值,并且自然继承了属性,则将属性值设置为inherit .
unset
将属性重置为其自然值,这意味着,如果该属性是自然继承的,则其作用类似于inherit ,否则它的作用类似于initial .

注意 :还有一个新值revert ,它对浏览器的支持有限.

Note: See Origin of CSS declarations in Introducing the CSS Cascade for more information on each of these and how they work.

我们可以查看链接列表,并探讨通用值的工作方式. 下面的实时示例使您可以使用CSS并查看进行更改后会发生什么. 玩代码确实是掌握HTML和CSS的最佳方法.

例如:

  1. 第二个列表项应用了my-class-1 . 这将设置嵌套在其中的<a>元素的颜色以进行继承. 如果删除规则,它将如何更改链接的颜色?
  2. 您了解第三和第四链接为什么是它们的颜色吗? 如果没有,请检查以上值的描述.
  3. 如果您为<a>元素定义新颜色,例如a { color: red; } a { color: red; }

 

Resetting all property values

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

在下面的示例中,我们有两个块引用. 第一个样式应用于blockquote元素本身,第二个样式应用于classquote,该类将all的值unsetunset .

 

尝试将all值设置为其他一些可用值,然后观察一下两者之间的区别.

Understanding the cascade

现在我们了解了为什么嵌套在HTML结构深处的段落与应用于正文的CSS具有相同的颜色,并且通过入门课程,我们了解了如何在文档的任何位置更改应用于某些内容的CSS —通过将CSS分配给元素或创建类. 现在,我们将正确看一看当多个元素可以样式化元素时,级联如何定义应用哪些CSS规则.

需要考虑三个因素,这里按重要性从高到低的顺序列出. 较早的优先于较晚的:

  1. Importance
  2. Specificity
  3. 源顺序

我们将自下而上查看这些内容,以了解浏览器如何准确地确定应使用哪种CSS.

Source order

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

Specificity

一旦了解了源顺序很重要的事实,您就会在某种程度上遇到一种情况,即您知道规则在样式表中稍后出现,但是会应用较早的,冲突的规则. 这是因为较早的规则具有更高的特异性 -它具有更高的特异性,因此被浏览器选择为应为元素设置样式的规则.

正如我们在本课程前面所看到的,类选择器比元素选择器具有更大的权重,因此在类上定义的属性将覆盖直接应用于元素的那些属性.

这里要注意的一点是,尽管我们正在考虑选择器以及应用于选择器的规则,但并不是整个规则都被覆盖,而是相同的属性.

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

 

现在让我们看一下浏览器如何计算特异性. 我们已经知道元素选择器的特异性很低,可以被类覆盖. 从本质上讲,分类型的选择器将获得一个点值,将这些值相加即可得出该特定选择器的权重,然后可以根据其他潜在匹配项对该权重进行评估.

选择器具有的特异性程度是使用四个不同的值(或分量)来衡量的,可以将其视为成千上万,数百个,十个和一个-四列中的四个数字:

  1. :如果声明位于style属性(也称为内联样式)内,则在此列中得分一. 这样的声明没有选择器,因此它们的特异性始终只是1000.
  2. 数百 :在此列中为整体选择器中包含的每个ID选择器打一分.
  3. 十分 :在此列中为整体选择器中包含的每个类选择器,属性选择器或伪类得分.
  4. 一个 :在此列中为整体选择器中包含的每个元素选择器或伪元素打一分.

注意 :通用选择器( * ),组合器( +>~ ,'')和否定伪类( :not )对特异性没有影响.

下表显示了一些孤立的示例,可帮助您提高心情. 尝试遍历这些内容,并确保您了解为什么它们具有我们赋予它们的特异性. 我们还没有详细介绍选择器,但是您可以在MDN 选择器参考中找到每个选择器的详细信息.

Selector Thousands Hundreds Tens Ones 总特异性
h1 0 0 0 1 0001
h1 + p::first-letter 0 0 0 3 0003
li > a[href*="en-US"] > .inline-warning 0 0 2 2 0022
#identifier 0 1 0 0 0100
没有选择器,元素的style属性中包含规则 1 0 0 0 1000

在继续之前,让我们看一个实际的例子.

 

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

  • 前两个选择器在争夺链接背景颜色的样式上竞争-第二个选择器获胜并使背景颜色变成蓝色,因为它在链中有一个额外的ID选择器:其特异性是201对101.
  • 第三和第四个选择器正在争夺链接文本颜色的样式-第二个选择器获胜并使文本变白,因为尽管元素选择器少了一个,但缺少的选择器却换成了一个类选择器,它值得十个比一个. 因此获胜的特异性是113比104.
  • 选择器5–7悬停在链接边界的样式上竞争. 选择器6显然输给了五个,特异性为23 vs. 24-链中元素选择器少了一个. 然而,选择器7击败了五个和六个,它在子链中具有与五个相同的子选择器数量,但是一个元素已换成类选择器. 因此获胜的特异性是33 vs 23和24.

注意 :仅为了便于理解,这仅是一个近似示例. 实际上,每种选择器类型都有其自己的特定性,不能被较低特定性级别的选择器覆盖. 例如,组合在一起的一百万个 选择器将无法覆盖一个 id选择器的规则.

评估特异性的更准确方法是对特异性水平分别评分,从最高开始,必要时降至最低. 只有在特定性水平内的选择器得分之间存在平局时,才需要评估下一个水平. 否则,您可以忽略较低特异性级别的选择器,因为它们永远不会覆盖较高特异性级别的选择器.

!important

您可以使用一个特殊的CSS来推翻所有上述计算,但是使用它时应该非常小心- !important . 这用于使特定属性和值成为最特定的事物,从而超越了级联的常规规则.

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

 

让我们逐步了解一下发生了什么—尝试删除一些属性,以查看如果发现难以理解将发生什么:

  1. 您会看到已经应用了第三条规则的colorpadding值,但没有应用background-color . 为什么? 确实,这三个都应该确实适用,因为源顺序中的较后规则通常会覆盖较早的规则.
  2. 但是,上面的规则会获胜,因为类选择器比元素选择器具有更高的特异性.
  3. 这两个元素都有betterclass ,但第二个元素也有winningid . 由于ID比类具有更高的特异性(页面上每个ID只能具有一个元素,但是具有相同类的许多元素-ID选择器针对的对象非常具体 ),红色背景色和1像素黑色边框应同时应用于第二个元素,第一个元素将获得灰色背景色,并且没有边框(如该类所指定).
  4. 第二个元素的确获得红色背景色,但没有边框. 为什么? 由于第二条规则中的!important声明(包括在border: none之后的声明) border: none表示即使ID具有更高的特异性,该声明也将取代上一条规则中的border值.

注意 :覆盖此!important声明的唯一方法是在源顺序中稍后具有相同特异性的声明中包含另一个!important声明,或具有较高特异性的声明.

知道!important存在是很有用的,这样当您在其他人的代码中遇到它时,您便知道它的含义. 但是,强烈建议您除非绝对必要,否则不要使用它. !important更改了级联通常的工作方式,因此它会使调试CSS问题变得非常困难,尤其是在大型样式表中.

您可能必须使用它的一种情况是,在CMS上工作时,您无法编辑核心CSS模块,而您确实想覆盖无法以其他任何方式覆盖的样式. 但实际上,如果可以避免,请勿使用它.

The effect of CSS location

Finally, it is also useful to note that the importance of a CSS declaration depends on what stylesheet it is specified in — it is possible for users to set custom stylesheets to override the developer's styles, for example the user might be visually impaired, and want to set the font size on all web pages they visit to be double the normal size to allow for easier reading.

To summarize

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

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

Web开发人员的样式表覆盖用户样式表是有意义的,因此可以按预期进行设计,但是如上所述,有时用户有充分的理由覆盖Web开发人员样式–这可以通过在其规则中使用!important来实现.

Test your skills!

我们在本文中介绍了很多内容,但是您能记住最重要的信息吗? 在继续进行之前,您可以找到一些其他测试来验证您是否保留了此信息—请参阅" 测试您的技能:Cascade" .

What's next

如果您了解本文的大部分内容,那么做得很好-您已经开始熟悉CSS的基本机制. 接下来,我们将详细介绍选择器.

如果您不完全了解级联,特异性和继承性,那就不用担心! 这绝对是迄今为止我们在本课程中讨论过的最复杂的事情,即使是专业的Web开发人员有时也会觉得棘手. 我们建议您在继续学习本课程的过程中再次返回本文,并继续进行思考.

如果您开始遇到样式不符合预期的奇怪问题,请返回此处. 这可能是一个特异性问题.

In this module

  1. Cascade and inheritance
  2. CSS selectors
  3. The box model
  4. Backgrounds and borders
  5. Handling different text directions
  6. Overflowing content
  7. Values and units
  8. Sizing items in CSS
  9. Images, media, and form elements
  10. Styling tables
  11. Debugging CSS
  12. Organizing your CSS