CSS 中的层叠、优先级和继承 | 青训营笔记

3,690 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

介绍

CSS 中的层叠、优先级和继承决定着如何将 CSS 应用到 HTML 中,以及如何解决冲突。在某些时候,我们在做一个项目过程中会发现一些应该产生效果的样式没有生效,通常的原因是你创建了两个应用于同一个元素的规则,而设计元素样式的规则可能不是期望的规则,因此需要了解这些机制是如何工作的。

层叠

是 CSS 的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。简单地说,就是 CSS 规则的顺序。它在 CSS 处于核心地位,CSS 的全称层叠样式表正是强调了这一点。有三个因素需要考虑,根据重要性排序(递增)如下:

  1. 资源顺序 - 如果你有超过一条规则,而且都是相同的权重,那么最后面的规则会应用。
  2. 优先级 - 决定在发生冲突的时候应该使用哪条规则。例如有些规则在最后出现,但是却应用了前面的具有冲突的规则,这是因为前面的有更高的优先级——它范围更小。
  3. 重要程度 - 特殊的 CSS 规则 !important,用于修改特定属性的值,能够覆盖普通规则的层叠。

大多数 @规则的 CSS 声明是参与层叠计算的,比如包含于 @media、@documents 或者@supports 的 CSS 声明,但是包含于 @keyframes 和 @font-face 的声明不参与计算,因为它们是作为一个整体参与层叠算法的筛选。另外,@import 和 @charset 遵循特定的算法,不受层叠算法影响。

还可以使用 CSS @规则 中的 @layer 声明一个级联层,同一层内的规则将级联在一起,优先级的顺序由声明层的顺序来决定,这给予了开发者对层叠机制的更多控制。

优先级

优先级是基于不同种类选择器组成的匹配规则。浏览器是根据优先级来决定当多个规则有不同选择器对应相同的元素的时候需要使用哪个规则。

  • 如果一个元素选择器不是很具体,例如选择页面上该类型的所有元素(或伪元素),则它的优先级就会低一些。
  • 如果一个类选择器稍微具体点,例如选择该页面中有特定 class 属性值(或其他属性选择器)的元素,则它的优先级就要高一点。
  • 如果一个类选择器更具体点,例如选择该页面中有特定 id 属性值的元素,则它的优先级就要更高一点。
  • 给元素添加的内联样式 (例如,style="font-weight:bold") 总会覆盖外部样式表的任何样式,因此可看作是具有最高的优先级。
  • 当在一个样式声明中使用一个 !important 规则时,将覆盖任何其他声明,与优先级无关。

下表列出了样式来源和其对应地重要程度(递增),例如 CSS 动画用 @keyframes @规则定义的值会覆盖全部普通值,但会被 !important 的值覆盖。

重要程度来源
1用户代理
2用户
3页面作者
4CSS 动画
5页面作者(!important
6用户(!important
7用户代理(!important
8css 过渡 (css transitions)
  1. 浏览器会有一个基本的样式表来给任何网页设置默认样式,称为用户代理样式。
  2. 网页的作者可以定义文档的样式,这是最常见的样式表。大多数情况下此类型样式表会定义多个,它们构成网站的视觉和体验,即主题。
  3. 读者,作为浏览器的用户,可以使用自定义样式表定制使用体验。
  4. 注意的是,原本级联水平高的声明应用了 !important 后,其优先级反而低,而原本级联水平低的声明应用了 !important 后,优先级反而高。

继承

每个CSS 属性定义的概述都指出了这个属性是默认继承的 ("Inherited: Yes") 还是默认不继承的 ("Inherited: no")。这决定了当你没有为元素的属性指定值时该如何计算值。

例如,你设置一个元素的 color 和 font-family,每个在里面的元素也都会有相同的属性,除非你直接在元素上设置属性。但是如果你在一个元素上设置 width 为 50% ,所有的后代元素则不会是父元素的宽度的 50% 。

尽管每个 CSS 属性页都列出了属性是否被继承,但我们通常可以通过常识来判断哪些属性属于默认继承。

  1. inherit 关键字允许显式的声明继承性,它对继承和非继承属性都生效。
  2. 可以使用 all 简写属性一次控制所有属性的继承,该属性将其值应用于所有属性。
  3. 常见可继承属性有:字体系列属性、文本系列属性(color、text-align、letter-spacing 等)。
  4. 常见不可继承属性有:背景系列属性、盒子模型属性(display、max-width、width、height、margin 、outline、border、padding 等)、定位属性(float、clear、position、top、overflow、clip、z-index 等)。

总结

CSS 声明的优先级取决于定义它的样式表和级联层。

  1. 可以设置自定义样式表来覆盖开发人员定义的样式:例如用户可能视力受损,并想在所有网页上设置两倍的正常字体大小,以便更容易进行阅读。
  2. 可以使用新特性级联层:你可以让非分层样式(在任何层之外声明的 CSS 样式会被按声明的顺序组合在一起,形成一个未命名的层,它会被当作最后声明的层)覆盖分层样式,或者你可以让后面的层中声明的样式覆盖先前的层中声明的样式。例如,作为开发人员,你可能无法编辑第三方的样式表,但你可以将外部的样式表导入级联层中,以便你自己的样式可以轻松地覆盖导入的样式,无需担心第三方选择器的优先级。