CSS的层叠与继承

170 阅读6分钟

概述

CSS 代表层叠样式表(Cascading Style Sheets),理解第一个词层叠(cascade)很重要——层叠的表现方式是理解 CSS 的关键。

在某些时候,在做一个项目过程中你会发现一些应该产生效果的样式没有生效。通常的原因是你创建了两个应用于同一个元素的规则。与层叠密切相关的概念是优先级(specificity),决定在发生冲突的时候应该使用哪条规则。

这里也有继承的概念,也就是在默认情况下,一些 css 属性继承当前元素的父元素上设置的值,有些则不继承。这也可能导致一些和期望不同的结果。

层叠

样式表层叠——简单的说,就是 CSS 规则的顺序很重要;当两条同级别的规则应用到一个元素的时候,写在后面的就是实际使用的规则。

层叠性就是CSS处理冲突的一种能力。层叠性只有在多个选择器选中同一个标签, 然后又设置了相同的属性, 才会发生层叠性。

元素被哪个属性命中有三个因素需要考虑,根据重要性排序如下:

  1. 资源顺序
  2. 优先级
  3. 重要程度

资源顺序

我们已经看到了顺序对于层叠的重要性。如果你有超过一条规则,而且都是相同的权重,那么最后面的规则会应用。可以理解为后面的规则覆盖前面的规则,直到最后一个开始设置样式。

资源顺序仅在规则的优先级相同时才体现出来,下面让我们看一下优先级:

优先级

概念 当多个选择器选中同一个标签, 并且给同一个标签设置相同的属性时, 如何层叠就由优先级来确定。

你会发现在一些情况下,有些规则在最后出现,但是却应用了前面的具有冲突的规则。这是因为前面的有更高的优先级——它范围更小,因此浏览器就把它选择为元素的样式。

就像前面看到的,类选择器的权重大于元素选择器,因此类上定义的属性将覆盖应用于元素上的属性。

这里需要注意虽然我们考虑的是选择器,以及应用在选中对象上的规则,但不会覆盖所有规则,只覆盖相同的属性。

这样可以避免重复的 CSS。一种常见的做法是给基本元素定义通用样式,然后给不同的元素创建对应的类。

浏览器如何计算优先级?

一个选择器的优先级可以说是由三个不同的值(或分量)相加,可以认为是百(ID)十(类)个(元素)——三位数的三个位数:

  • ID:选择器中包含 ID 选择器则百位得一分。
  • :选择器中包含类选择器、属性选择器或者伪类则十位得一分。
  • 元素:选择器中包含元素、伪元素选择器则个位得一分。

备注: 通用选择器(*)、组合符(+>~、' ')和调整优先级的选择器(:where())不会影响优先级。

否定(:not())和任意匹配(:is())伪类本身对优先级没有影响,但它们的参数则会带来影响。参数中,对优先级算法有贡献的参数的优先级的最大值将作为该伪类选择器的优先级。

下面有几个单独的例子,有空可以看看。试着思考下,理解为什么优先级是这样定的。我们还没有深入介绍选择器,不过你可以在 MDN 的选择器参考页面找到每个选择器的详细信息。

选择器ID元素优先级
h10010-0-1
h1 + p::first-letter0030-0-3
li > a[href*="en-US"] > .inline-warning0220-2-2
#identifier1001-0-0
button:not(#mainBtn, .cta)1011-0-1

内联样式,即 style 属性内的样式声明,优先于所有普通的样式,无论其优先级如何。这样的声明没有选择器,但它们的优先级可以理解为 1-0-0-0;即无论选择器中有多少个 ID,它总是比其它任何优先级的权重都要高。

!important

有一个特殊的 CSS 可以用来覆盖所有上面所有优先级计算,不过需要很小心的使用——!important。用于修改特定属性的值,能够覆盖普通规则的层叠。

备注: 了解 !important 是为了在阅读别人代码的时候知道有什么作用。但是,强烈建议除了非常情况不要使用它。 !important 改变了层叠的常规工作方式,它会使调试 CSS 问题非常困难,特别是在大型样式表中。

备注: 覆盖 !important 唯一的办法就是另一个 !important 具有相同优先级而且顺序靠后,或者更高优先级。

在一种情况下,你可能不得不使用它:当你不能编辑核心的 CSS 模块,不能用任何其他方式覆盖,而你又真的想要覆盖一个样式时。但说真的,如果可以避免的话就不要用它。

  • 优先级

!important>行内样式>id选择器>类选择器>标签选择器>通配符>继承

1、继承样式的权重为0。即在嵌套结构中,不管父元素样式的权重多大,被子元素继承时,他的权重都为0,也就是说子元素定义的样式会覆盖继承来的样式。

2、行内样式优先。应用style属性的元素,其行内样式的权重非常高,可以理解为远大于100。

3、权重相同时,CSS遵循就近原则。也就是说靠近元素的样式具有最大的优先级,或者说排在最后的样式优先级最大。

4、CSS定义了一个!important命令,该命令被赋予最大的优先级。也就是说不管权重如何以及样式位置的远近,!important都具有最大优先级。

继承

继承也需要在上下文中去理解——一些设置在父元素上的 CSS 属性是可以被子元素继承的,有些则不能。

举一个例子,如果你设置一个元素的 colorfont-family,每个在里面的元素也都会有相同的属性,除非你直接在元素上设置属性。

!!!继承的前提是本元素没有设置相对应的属性

控制继承

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

  • inherit

    设置该属性会使子元素属性和父元素相同。实际上,就是“开启继承”。

  • initial

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

  • revert (en-US)

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

  • revert-layer (en-US)

    将应用于选定元素的属性值重置为在上一个层叠层中建立的值。

  • unset

    将属性重置为自然值,也就是如果属性是自然继承那么就是 inherit,否则和 initial 一样