Skip to content

层叠、优先级和继承

TIP

❑ 组成层叠的四个部分
❑ 层叠和继承的区别
❑ 如何控制样式和元素的对应关系
❑ 简写声明的常见误区

层叠

当声明冲突时,层叠会依据三种条件解决冲突:

(1) 样式表的来源:作者样式 > 浏览器默认样式
(2) 选择器优先级:id 选择器 > 类选择器 > 标签选择器
(3) 源码顺序:样式在样式表里的声明顺序,优先级相同的情况下,采用“后来居上”原则

结论:

  1. 当声明之间有冲突时,看选择器的优先级:id 选择器 > 类选择器 > 标签选择器
  2. 作者样式的 !important > 行内样式
  3. 行内样式的 !important 优先级最高,谁也无法覆盖

样式表的来源

1.用户代理样式

如果长期使用 CSS,你大概习惯了覆盖用户代理的样式。这种做法实际上就是利用了层叠的样式来源规则。你写的样式会覆盖用户代理样式,因为来源不同。

2.!important 声明

标记了 !important 的声明会被当作更高优先级的来源,因此总体的优先级按照由高到低排列如下所示:
(1) 作者的 !important
(2) 作者
(3) 用户代理

思考

作者的 !important 声明,是在跟谁竞争优先级呢?

理解优先级

不理解样式的来源照样可以写 CSS,因为 99% 的网站样式是来自同样的源。

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

1.行内样式

如果用 HTML 的 style 属性写样式,这个声明只会作用于当前元素。实际上行内元素属于“带作用域的”声明,它会覆盖任何来自样式表或者 <style> 标签的样式。行内样式没有选择器,因为它们直接作用于所在的元素。

为了在样式表里覆盖行内声明,需要为声明添加 !important,这样能将它提升到一个更高优先级的来源。但如果行内样式也被标记为 !important,就无法覆盖它了。

结论:

  1. 当声明之间有冲突时,看选择器的优先级:id 选择器 > 类选择器 > 标签选择器
  2. 作者样式的 !important > 行内样式
  3. 行内样式的 !important 优先级最高,谁也无法覆盖

2.选择器优先级

优先级的准确规则如下:
❑ 如果选择器的 id 数量更多,则它会胜出(即它更明确)。
❑ 如果 id 数量一致,那么拥有最多类的选择器胜出。
❑ 如果以上两次比较都一致,那么拥有最多标签名的选择器胜出。

伪类选择器(如 :hover)和属性选择器(如 [type="input"])与一个类选择器的优先级相同。通用选择器(*)和组合器(>+~)对优先级没有影响。

3.优先级标记

选择器权重
!important无穷大
行内样式1,0,0,0
id 选择器0,1,0,0
类、伪类、属性选择器0,0,1,0
标签、伪元素选择器0,0,0,1
通用选择器 *、组合器(>~+)、否定伪类 :not 选择器0,0,0,0
继承的样式没有权值

通用选择器 *,组合器(>~+),否定伪类 :not 对优先级没有影响,不作计入。

:not 伪类不像其它伪类,它不会增加选择器的优先级。:not(X) 伪类的优先级即为它参数选择器 X 的优先级。

4.关于优先级的思考

通常最好让优先级尽可能低,这样当需要覆盖一些样式时,才能有选择空间。

源码顺序

1.链接样式和源码顺序

这个顺序的记忆口诀是“LoVe/HAte”(“爱/恨”),即 link(链接)、visited(访问)、hover(悬停)、active(激活)。

思考

以 Typora 的主题制作为例,写 CSS 样式代码时,应该遵循的源码顺序是什么?

How to organize CSS @ 9elements
The Definitive Guide to CSS Styling Order
High-level advice and guidelines for writing sane, manageable, scalable CSS

2.层叠值

浏览器遵循三个步骤,即来源、优先级、源码顺序,来解析网页上每个元素的每个属性。如果一个声明在层叠中“胜出”,它就被称作一个层叠值。元素的每个属性最多只有一个层叠值。

层叠值——作为层叠结果,应用到一个元素上的特定属性的值。

如果一个元素上始终没有指定一个属性,这个属性就没有层叠值。

框图总结

CSS 样式优先级

两条经验法则

(1) 在选择器中不要使用 id。就算只用一个 id,也会大幅提升优先级。当需要覆盖这个选择器时,通常找不到另一个有意义的 id,于是就会复制原来的选择器,然后加上另一个类,让它区别于想要覆盖的选择器。
(2) 不要使用 !important。它比 id 更难覆盖,一旦用了它,想要覆盖原先的声明,就需要再加上一个 !important,而且依然要处理优先级的问题。

继承

如果一个元素的某个属性没有显式设定,则可能会继承某个祖先元素的值。

支持继承的属性

  1. 字体系列属性
    font-family:字体系列
    font-weight:字体的粗细
    font-size:字体的大小
    font-style:字体的风格

  2. 文本系列属性
    text-indent:文本缩进
    text-align:文本水平对齐
    line-height:行高
    word-spacing:单词之间的间距
    letter-spacing:中文或者字母之间的间距
    text-transform:控制文本大小写(就是 uppercaselowercasecapitalize 这三个)
    color:文本颜色

  3. 元素可见性
    visibility:控制元素显示隐藏

  4. 列表布局属性
    list-style:列表风格,包括 list-style-typelist-style-image

  5. 光标属性
    cursor:光标显示为何种形态

无继承的属性

  1. display:规定元素应该生成的框的类型

  2. 文本属性:
    vertical-align:垂直文本对齐
    text-decoration:规定添加到文本的装饰
    text-shadow:文本阴影效果
    white-space:空白符的处理
    unicode-bidi:设置文本的方向

  3. 盒子模型的属性:widthheightmarginborderpadding

  4. 背景属性:backgroundbackground-colorbackground-imagebackground-repeatbackground-positionbackground-attachment

  5. 定位属性:floatclearpositiontoprightbottomleftmin-widthmin-heightmax-widthmax-heightoverflowclipz-index

  6. 生成内容属性:contentcounter-resetcounter-increment

  7. 轮廓样式属性:outline-styleoutline-widthoutline-coloroutline

  8. 页面样式属性:sizepage-break-beforepage-break-after

  9. 声音样式属性:pause-beforepause-afterpausecue-beforecue-aftercueplay-during

特殊值

有两个特殊值可以赋给任意属性,用于控制层叠:inheritinitial

通常我们会给网页的所有链接加上一个字体颜色(如果不加的话,就会以用户代理样式为准)。这个颜色也会作用于页脚的“Terms of use”链接。

示例 HTML 代码:

HTML
<footer class="footer">
  &copy; 2016 Wombat Coffee Roasters &mdash;
  <a href="/terms-of-use">Terms of use</a>
</footer>

示例 CSS 代码:

CSS
.footer {
  color: #666;
  background-color: #ccc;
  padding: 15px 0;
  text-align: center;
  font-size: 14px;
}

通过 F12 查看 .footer 内部的 a 元素,可以看到,用户代理样式的伪类 a:-webkit-any-link,覆盖了作者样式的类选择器 .footercolor 属性不是会继承吗,为什么 footer 里的 a 标签没有继承 footer 的灰色,仍然是蓝色的呢? 这是因为,虽然子元素有默认继承父元素样式的特点,但是默认继承的样式其优先级最低,通常会被用户代理样式覆盖。如果需要覆盖用户代理样式,可以通过关键字 inherit 显式指定继承父元素的样式。

继续向样式表中添加如下代码:

CSS
.footer {
  color: #666;
  background-color: #ccc;
  padding: 15px 0;
  text-align: center;
  font-size: 14px;
}

.footer a {
  color: inherit;
}

加入这段代码之后,显示使用 inherit 指定继承的样式就可以覆盖用户代理样式,此时“Terms of use”链接会变成灰色。

结论:显式使用 inherit 继承的样式(灰色) > 用户代理样式(蓝色) > 默认继承的样式(灰色)

层叠与继承

简写属性

总结

❑ 控制选择器的优先级
❑ 不要混淆层叠和继承
❑ 某些属性会被继承,包括文本、列表、表格边框相关的属性
❑ 不要混淆 initialauto
❑ 简写属性要注意 TRouBLe 的顺序,避免踩坑