本文为读 Cascade and inheritance 的笔记。
着重理解 CSS 三个基础概念——cascade, specificity, inheritance。这三点控制 CSS 如何应用于 HTML,样式之间的冲突如何解决。
Conflicting rules
CSS 的全称是 Cascading Style Sheets。当出现矛盾规则(两个不同的值应用到同一个选择器的同一个属性上)时,cascade, specificity 是解决这类问题的措施。
Cascade
样式层叠意味着,原始样式、层叠的部分以及 CSS 规则的顺序是重要的。 当两个规则来自相同的层叠层,并且有着相同的特异性,那么最后定义的那一个的样式会被用在 HTML 中。
举例:
h1 {
color: red;
}
h1 {
color: blue;
}
两个 style blocks 具有相同特异性,所以两者的顺序会决定哪一个的样式会被应用。根据前述规则,h1 最终的颜色会是蓝色。
Specificity
特异性是浏览器使用的算法,用来决定将哪一个属性值应用到元素上。
如果在多个样式块(有着不同选择器)中配置了相同属性的不同值。特异性决定哪一个属性值会被应用到元素上。特异性是一种方法——它能确定一个选择器有多特别。
- 一个元素选择器的特异性最小,因为它会选择所有是该元素的元素。它的特异性权重最小。
- 类选择器的权重提升一些,它只会选择具有某个类的元素,与元素选择器相比权重增大一些。
举例:
.main-heading {
color: red;
}
h1 {
color: blue;
}
h1 元素的颜色是红色。因为 class 选择器的特异性权重更高,所以无视顺序问题。
Inheritance
什么是继承?
一些为父元素设置的样式会由子元素继承,而另外一些样式(为父元素设置的)则不会被子元素继承。
举例:
body {
color: blue;
}
span {
color: black;
}
<p>As the body has been set to have a color of blue this is inherited through the descendants.</p> <p>We can change the color by targeting the element with a selector, such as this <span>span</span>.</p>
这两段文字,除了 span 其余全是黑色。
有些属性可继承,如 color, font-family;有些则不可以,如 width。
如何查找?
在每一个 CSS 属性的页面都有一个"Formal definition"。在那里可以找到当前属性是否可继承。
Understanding how the concepts work together
通过 Firefox Developer Tools 可以很方便地查看、更改、调试,CSS 规则。
Understanding inheritance
<ul class="main"> <li>Item One</li> <li>Item Two <ul> <li>2.1</li> <li>2.2</li> </ul> </li> <li>Item Three <ul class="special"> <li>3.1 <ul> <li>3.1.1</li> <li>3.1.2</li> </ul> </li> <li>3.2</li> </ul> </li> </ul>
.main {
color: rebeccapurple;
border: 2px solid #ccc;
padding: 1em;
}
.special {
color: black;
font-weight: bold;
}
color 是可继承的。所以 <li>
继承了 .main 的样式;.special
的子元素变成了黑色。
width、margin、padding、border 不可继承。
Controlling inheritance
CSS 提供了五个通用属性值,用来控制 CSS 继承。每一个 CSS 属性都适用。
这五个属性值分别为:inherit, initial, revert, revert-layer, unset。
通过快捷属性 all 能够一次性重置很多属性。
Understanding the cascade
决定层叠优先级的三个要素:
- Source order
- Specificity
- Importance
- Source order
<!–listend–>
p {
color: red;
}
p {
color: black;
}
根据 Source order,两个 CSS block 内的 Specificity 权重是一致的。哪一个样式会被应用,取决于顺序,哪一个在后会被应用。因此,p 的颜色是黑色。
- Specificity
如果两个 Specificity 权重不一致,如下:
.para {
color: red;
}
p {
color: black;
}
只通过 Source order 确定 CSS 的样式选择就不可行了。由这段代码可得出结论: 类选择器比类选择器具有更大的权重 。
注意:应用于 HTML 文本和组件的各 CSS block 的样式并非全被覆盖,只有那些在多个 CSS block 声明的属性会被覆盖。 这样做的好处是避免重复设置样式。通常的实践是:先定义通用样式,然后再根据各组件需要修改部分。
h2 {
font-size: 2em;
color: #000;
font-family: Georgia, "Times New Roman", Times, serif;
}
.small {
font-size: 1em;
}
.bright {
color: rebeccapurple;
}
后两个类同样是应用在 h2 元素上。
一个选择器的 specificity 数目由三个值确定:ID、CLASS、ELEMENT。
- Identifiers: 在整个选择器中,出现一个 id 选择器加 1
- Classes: 在整个选择器中,出现一个类、属性或伪类选择器加 1
- Elements: 在整个选择器中,出现一个元素或伪元素选择器加 1
注意:通用选择器( *
)、选择符(+, >, ~,
'')和某些特定选择器(:where())不具备 specificity。
两个伪类 :not()
和 :is()
无法改变
specificity,但它们的参数能够改变。The specificity each contributes to
the specificity algorithm is the specificity of the selector in
parameter that has the greatest weight.(这句不理解)
一些 specificity 计算的例子:
Selector | Identifiers | Classes | Elements | Total specificity |
---|---|---|---|---|
h1 |
0 | 0 | 1 | 0-0-1 |
h1 + p::first-letter |
0 | 0 | 3 | 0-0-3 |
li > a[href* "en-US"] > .inline-warning= |
0 | 2 | 2 | 0-2-2 |
#identifier |
1 | 0 | 0 | 1-0-0 |
button:not(#mainBtn, .cta) |
1 | 0 | 1 | 1-0-1 |
注意:每一个选择器都有自己的特异性(specificity),低特异性水平的选择器不能覆盖掉高特异性水平水的选择器。举例,10 个类选择器的特异性比不过 1 个 id 选择器的特异性。
评估特异性的最佳方式是为不同水平的特异性从高到低打分。在进行比较时,只有两个集合的对应序列打分相同时,才可进行下一序列的比较。
两个特异性集合:(a, b, c), (d, e, f),只有当 a=d
时,b 和 e
的比较才有意义。如果 a>d
,那么 (a, b, c) 的特异性大于 (d, e, f)。如果
a<d
,那么 (d, e, f) 的特异性大于 (a, b, c)。
- 内嵌样式
内嵌样式指的是通过全局属性 style 来对具体元素设置样式。它的特异性最高 (1-0-0-0)。
<p style="color: red;">This is a paragraph.</p>
- !important
有时,设置样式的时候,会因为太过复杂而导致样式产生冲突。想要样式不发生改变,可以通过在样式属性值后面加
!important
。
p {
color: red !important;
}
它会破坏正常的特异性。它会覆盖一般的层叠规则,甚至是内嵌样式。
*注意:要在确定需要它的情况下使用。因为它对正常 CSS 样式的破坏,使得对包含它的 CSS 调试变得很困难,随着 CSS 的复杂程度增长,调试的困难程度跟着倍增。*
The effect of CSS location
最后,需要注意的是,CSS 声明的优先级取决于指定它的样式表和级联层。
- Order of overriding declarations
样式冲突的优先级(高优先级的样式被应用,优先级由低到高):
- 浏览器的默认样式
- 用户的自定义样式
- 开发者的自定义样式
- 开发者自定义样式中有
!important
的部分样式 - 用户自定义样式中有
!important
的部分样式 - 浏览器默认样式中有
!important
的部分样式 - Order of cascade layers
什么是 @layer1?
它能够用来声明一个级联层,还可用于定义多层级联情况下的优先顺序。
在级联层中声明样式时,层的顺序决定了优先级。层外的所有样式形成一个未命名的层,位于其他层的最后,(在正常样式中)是有着最高的优先级的级联层。在正常的样式中,层越靠后优先级越高。如果有
!important
,正好相反,层越靠前优先级越高。在级联层中,内嵌样式的优先级高于所有
author 样式,与级联层无关。
[@layer - CSS - MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer)