CSS

CSS基础-层叠、优先级与继承

This entry is part 3 of the seriesenjoy-css

冲突

CSS 本质上就是声明规则,即在各种条件下,我们希望产生的特定效果。 在某些时候,在做一个项目过程中你会发现一些应该产生效果的样式没有生效。通常的原因是你创建了两个应用于同一个元素的规则, 且两个规则发生了冲突。要想实现最终的效果,就需要理解CSS里的层叠。


为了演示, 我构建了一个简单的网页头部。上面是网站标题,下面是一排导航按钮,其中前两个背景为青蓝色,最后一个时橘黄色,用来表示其特殊性。

Code Playground
<link rel='stylesheet' href='./styles.css' >
<style>
  button {
    background: lightblue;
  }
  /* 👆规则冲突👇*/
  .featured {
    background: orange;
  }
</style>
<body>
  <header>
    <h1>Slash Spaces</h1>
    <nav>
      <button>Posts</button>
      <button>Tags</button>
      <button class="featured">Series</button>
    </nav>
  </header>
</body>

对于button元素我们声明了两个规则, 且这两个规则中包含冲突的声明:

两个规则尝试给按钮设置不同的背景颜色,哪一个会生效呢? 浏览器为了解决这个问题会遵循一系列规则,因此最终的效果是可以预测的。

层叠

下面来分享层叠的规则。当声明冲突时,层叠会依据三种条件解决冲突:

  1. 样式表的来源: 样式是从哪里来的,包括你的样式和浏览器默认样式。
  2. 优先级: 哪些选择器比另一些选择器更重要。
  3. 源码顺序: 样式在样式表里的声明顺序。

样式表的来源

你添加到网页里的样式表并不是浏览器唯一使用的样式表,还有其他类型或来源的样式表。这些来源包括:

  1. 用户代理样式(user agent stylesheet):即浏览器默认样式表。 这些是默认情况下您的浏览器应用于 HTML 元素的样式
  2. 用户样式: 作为浏览器的用户,可以使用自定义样式表定制使用体验, 例如允许用户为网页编写自定义 CSS 的浏览器扩展程序
  3. 作者样式: 作为网页的作者,您自行编写的样式。这是最常见的样式表。

样式表的来源规则有一个例外: 标记为!important 的声明。 如下所示,在声明的后面加上!important, 该声明就会被标记为重要的声明:

标记了!important的声明会被当做更高优先级的来源,因此总体的优先级按照由低到高排列如下所示:

样式表来源的优先级

假设层叠的顺序相同,则使用那个规则取决于优先级

优先级

如果无法用来源解决冲突声明,浏览器会尝试检查它们的优先级。 浏览器通过优先级来判断哪些属性值与一个元素最为相关,从而在该元素上应用这些属性值。

浏览器将优先级分为两部分:HTML的行内样式选择器的优先级

行内样式

行内样式使用style属性给当前元素设置样式,它会覆盖任何来自样式表或者<style>标签的样式

Code Playground
<link rel='stylesheet' href='./styles.css'>
<style>
  button {
    background: lightblue;
  }
</style>
<body>
  <header>
    <h1>Slash Spaces</h1>
    <nav>
      <button>Posts</button>
      <button>Tags</button>
      <!-- 📌 用style属性设置行内样式 -->
      <button style="background: orange">Series</button>
    </nav>
  </header>
</body>

选择器优先级

优先级的第二部分由选择器决定。 每条选择器都会获得一个评分x-y-z,评分分越高的选择器优先级越高。

评分详解
  • x: 代表id选择器数量,可以理解为 百分位
  • y: 代表类、属性、伪类选择器数量, 可以理解为十分位
  • z: 代表元素选择器和伪元素选择器数量, 可以理解为个位

最终评分为: 100x + 10y + z

为便于参考, 以下选择器评分为 1-4-1141

下面这张图详细列举了各种选择器的评分, 其中还有4个数和5个数的标记:

  • inline-style: 1-0-0-0
  • !important: 1-0-0-0-0
选择器评分详细列举

源码顺序

层叠的第三步,也是最后一步,是源码顺序。如果两个声明的来源和优先级相同,其中一个声明在样式表中出现较晚,或者位于页面较晚引入的样式表中,则该声明胜出。

Code Playground
<link rel='stylesheet' href='./styles.css'>
<style>
  .nav button {
    /* 优先级 0-1-1, 因较早出现, 会被覆盖 💩 */
    background: lightblue;
  }

  /* 👆 可以尝试交换上下两个规则集的位置 👇 */

  button.featured {
    /* 优先级 0-1-1, 但因出现较晚,因此该声明胜出 ✌🏻 */
    background: orange;
  }
</style>
<body>
  <header>
    <h1>Slash Spaces</h1>
    <nav class="nav">
      <button>Posts</button>
      <button>Tags</button>
      <button class="featured">Series</button>
    </nav>
  </header>
</body>

继承

CSS继承是一个重要的概念,它描述了当一个CSS属性没有在元素上显式设置时,该属性如何从其父元素继承。这意味着,如果一个元素的某个属性没有被指定,那么它将自动从其父元素那里继承该属性的值。

inherit

可以使用 inherit 关键字使任何属性继承于其父元素的值。

Code Playground
<link rel='stylesheet' href='./styles.css'>
<style>
/* 全局按钮文本颜色 */
button {
  color: red;
}

/* 导航文本颜色 */
nav {
  color: orange;
}

/* 📌从导航继承文本颜色*/
nav .featured {
  color: inherit;
}
</style>
<body>
  <header>
    <h1>Slash Spaces</h1>
    <nav>
      <button>Posts</button>
      <button>Tags</button>
      <button class="featured">Series</button>
    </nav>
  </header>
</body>

initial

有时,你需要撤销作用于某个元素的样式。这可以用initial关键字来实现。每一个CSS属性都有初始(默认)值。如果将initial值赋给某个属性,那么就会有效地将其重置为默认值,这种操作相当于硬复位了该值

Code Playground
<link rel='stylesheet' href='./styles.css'>
<style>
/* 全局按钮文本颜色 */
button {
  color: red;
}

/* 导航文本颜色 */
nav {
  color: orange;
}

/* 📌恢复初始值 */
nav .featured {
  color: initial;
}
</style>
<body>
  <header>
    <h1>Slash Spaces</h1>
    <nav>
      <button>Posts</button>
      <button>Tags</button>
      <button class="featured">Series</button>
    </nav>
  </header>
</body>

理解这些概念是如何系统工作的

该视频展示了如何使用 Firefox 的开发者工具来检查网页的级联和优先级等

Questions? Let's chat

discord logoOPEN DISCORD
6423
members online
previous article
CSS基础-选择器
next article
CSS基础-颜色

A TypeScript Full Stack Blog

Share articles about Typescript, React, Next.js, Node.js and Css from time to time.
No spam, unsubscribe at any time.