CSS 中的“C”:层叠

Avatar of Thomas Yip
Thomas Yip

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 价值 200 美元的免费积分!

承接 Geoff 关于 CSS 中的第二个“S” 的介绍文章,现在让我们将聚光灯转向 CSS 中的“C” - 我们称之为层叠。这是事情开始变得混乱,甚至有时令人困惑的地方。

您是否曾经编写过一个 CSS 属性,但该值似乎不起作用?也许您不得不使用 !important 来使其生效。或者,您可能求助于在 HTML 文件中的元素上内联编写 CSS。

<div style="background:orange; height:100px; width:100px;">
  Ack, inline!
</div>

说到内联样式,您是否想知道为什么 SVG 编辑器使用它们而不是单独的 CSS 文件?这看起来有点奇怪,对吧?

<svg id="icon-logo-star" viewBox="0 0 362.62 388.52" width="100%" height="100%">
  <style>
    .logo {
      fill: #ff9800;
    }
  </style>
  <title>CSS Tricks Logo</title>
  <path class="logo" d="M156.58 239l-88.3 64.75c-10.59 7.06-18.84 11.77-29.43 11.77-21.19 0-38.85-18.84-38.85-40 0-17.69 14.13-30.64 27.08-36.52l103.6-44.74-103.6-45.92C13 142.46 0 129.51 0 111.85 0 90.66 18.84 73 40 73c10.6 0 17.66 3.53 28.25 11.77l88.3 64.75-11.74-104.78C141.28 20 157.76 0 181.31 0s40 18.84 36.5 43.56L206 149.52l88.3-64.75C304.93 76.53 313.17 73 323.77 73a39.2 39.2 0 0 1 38.85 38.85c0 18.84-12.95 30.61-27.08 36.5l-103.61 45.91L335.54 239c14.13 5.88 27.08 18.83 27.08 37.67 0 21.19-18.84 38.85-40 38.85-9.42 0-17.66-4.71-28.26-11.77L206 239l11.77 104.78c3.53 24.72-12.95 44.74-36.5 44.74s-40-18.84-36.5-43.56z"></path>
</svg>

好吧,层叠与之关系很大。继续阅读以了解样式方法如何影响应用于元素的内容,以及如何利用层叠的优势,因为相信我,一旦您掌握了它,它将是一件美妙的事情。

TL;DR:直接跳转到 CSS 排序图,以直观了解所有内容的工作原理。

层叠关心样式的编写方式和位置

您可以通过多种方式将 CSS 规则应用于元素。以下是将 stroke: red; 应用于同一元素的示例。这些示例按升序优先级排序,其中最高优先级位于底部

<!-- Inheritance -->
<g style="stroke: red">
  <rect x="1" y="1" width="10" height="10" /> <!-- inherits stroke: red -->
</g>

<!-- Inline attributes -->
<rect x="1" y="1" width="10" height="10" stroke="red" />

<!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css">

<!-- Embedded styles -->
<style>
  rect { stroke: red; }
</style>

<!-- Different specificity or selectors -->
rect { stroke: red; }
.myClass { stroke: red; }
#myID { stroke: red; }

<!-- Inline style -->
<g style="stroke: red"></g>

<!-- Important keyword -->
<g style="stroke: red !important"></g>

继承?嵌入?外部?内联?特异性?重要?是的,很多术语被抛来抛去。让我们稍微分解一下,因为每一个术语都决定了网页加载时浏览器最终使用什么。

元素可以从其他元素继承样式

HTML 和 SVG 元素都可以继承应用于其他元素的 CSS 规则。我们称之为父子关系,其中应用 CSS 的元素是父元素,包含在父元素内部的元素是子元素。

<div class="parent">
  <div class="child">I'm the child because the parent is wrapped around me.</div>
</div>

如果我们设置父元素的文本颜色,并且没有在子元素上声明文本颜色,那么子元素将向上查找父元素以了解其文本的颜色应该是什么。我们称之为继承,它是样式如何层叠到它匹配的元素的典型例子......或者“向上冒泡”到下一个匹配的样式的链中。

但是,继承在样式方法中具有最低优先级。换句话说,如果子元素有一个特定于它的规则,那么继承的值将被忽略,即使继承的值可能有一个重要的关键字。以下是一个例子

<div class="parent" style="color: red !important;">
  <div class="child">I'm the child because the parent is wrapped around me.</div>
</div>

查看 CodePen 上 Geoff Graham 的笔 子元素忽略带有 !important 的内联继承 (@geoffgraham)。

SVG 内联属性

对于 SVG 元素,我们还可以使用内联属性应用样式,其中内联属性在层叠中具有第二低优先级。这意味着样式表中的 CSS 规则将能够覆盖它们。

<rect x="1" y="1" width="10" height="10" stroke="red" />
rect {
  stroke: blue;
}

查看 CodePen 上 Geoff Graham 的笔 样式表覆盖 SVG 内联属性 (@geoffgraham)。

大多数 SVG 编辑器使用内联属性来实现可移植性;也就是说,能够复制某些元素并粘贴到其他地方而不会丢失属性。然后,用户可以使用生成的 SVG 并使用外部样式表对其元素进行样式化。

样式表

样式表分为两种:外部嵌入式

<!-- External style sheet -->
<link rel="stylesheet" href="/path/to/stylesheet.css">

<!-- Embedded styles -->
<style>
  div { border: 1px solid red }
</style>

嵌入式样式外部样式表具有相同的优先级。因此,如果您具有相同的 CSS 规则,则适用排序规则

查看 CodePen 上 Geoff Graham 的笔 嵌入式样式覆盖样式表规则 (@geoffgraham)。

所有样式表都遵循排序规则,其中定义较晚的文件将比定义较早的文件具有更高的优先级。在本例中,stylesheet-2.css 将优先于 stylesheet-1.css 文件,因为它最后定义。

<link rel="stylesheet" href="/path/to/stylesheet-1.css">
<link rel="stylesheet" href="/path/to/stylesheet-2.css">

特异性或选择器

您选择元素的方式也将决定应用哪些规则,其中标签(例如 <p><div>)、类(例如 .my-class)和 ID(例如 #myI-id)具有升序优先级。

查看 CodePen 上 Geoff Graham 的笔 按选择器划分特异性 (@geoffgraham)。

在上面的示例中,如果您有一个同时具有 .my-class#my-id 的 div 元素,那么边框将为红色,因为 ID 比类和标签具有更高的优先级。

*特异性比排序规则具有更高的优先级,因此,无论您的规则位于顶部还是底部。特异性仍然具有更高的优先级,并且将被应用。

排序

CSS 规则始终从左到右,然后从上到下优先级排序。

<!-- Blue will be applied because it is on the right -->
<div style="border: 1px solid red; border: 1px solid blue;"></div> 

<style>
  div {
    border: 1px solid red;
    border: 1px solid blue; /* This will be applied because it is at the bottom */
  }
</style>

内联样式

内联样式具有第二高的优先级,仅次于 !important 关键字。这意味着内联样式仅会被重要关键字覆盖,而不会被其他任何东西覆盖。在内联样式中,适用正常的排序规则,从左到右,从上到下。

<div style="1px solid red;"></div>

重要关键字

说到 !important 关键字,它用于覆盖排序、特异性和内联规则。换句话说,它拥有难以置信的力量。

覆盖内联规则

<style>
  div {
    /* This beats inline styling */
    border: 1px solid orange !important;
    /* These do not */
    height: 200px;
    width: 200px;
  }
</style>

<div style="border: 1px solid red; height: 100px; width: 100px;"></div>

在上面的示例中,如果没有重要关键字,div 将具有红色边框,因为内联样式比嵌入式样式具有更高的优先级。但是,使用重要关键字,div 边框变为橙色,因为重要关键字比内联样式具有更高的优先级。

使用 !important 可以非常有用,但应谨慎使用。Chris 对何时使用它有一些想法

覆盖特异性规则

如果没有重要关键字,这个 div 边框将为蓝色,因为在特异性中,类比标签具有更高的优先级。

<style>
  /* Classes have higher priority than tags */
  .my-class {
    border: 1px solid blue;
    height: 100px;
    width: 100px;
  }
  
  div { 
    border: 1px solid red;
    height: 200px;
    width: 200px;
  }
</style>

<div class="my-class"></div>

查看 CodePen 上 Geoff Graham (@geoffgraham) 的 类比标签

但是!将重要关键字添加到标签规则中,会告诉元素忽略级联并优先于类规则。

<style>
  .my-class { border: 1px solid red; }
  
  /* The important keyword overrides specificity priority */
  .my-class { border: 1px solid blue !important; }
</style>

<div class="my-class"></div>

查看 CodePen 上 Geoff Graham (@geoffgraham) 的 !important 忽略级联

覆盖排序规则

好的,我们已经讨论过规则顺序如何影响特异性:底部优于顶部,右侧优于左侧。确保覆盖此规则的方法是再次使用!important

在本例中,即使蓝色边框是底部规则,div 也会采用红色边框。感谢!important的巧妙工作。

<style>
  div { border: 1px solid red !important; } /* This wins, despite the ordering */
  div { border: 1px solid blue; }
</style>

<div></div>

查看 CodePen 上 Geoff Graham (@geoffgraham) 的 重要性胜过排序

可视化级联

谁知道 CSS 中的“C”包含了如此多的含义?我们在这里涵盖了很多内容,希望这有助于阐明我们如何编写样式以及样式如何受到影响和应用的方式。级联是一个强大的功能。关于如何正确使用它的观点很多,但您可以看到属性是如何传递和继承到元素的。

更喜欢视觉学习者?这里有一张将所有内容整合在一起的图表。

下载图表