CSS选择器及其优先级

... 2025-7-10 CSS 大约 7 分钟

# 选择器


# 优先级

!important > 行内样式 > ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性

浏览器通过优先级来判断哪些属性值与一个元素最为相关,从而在该元素上应用这些属性值。优先级是基于不同种类选择器组成的匹配规则。

优先级就是分配给指定的 CSS 声明的一个权重,它由 匹配的选择器中的 每一种选择器类型的 数值 决定。

而当优先级与多个 CSS 声明中任意一个声明的优先级相等的时候,CSS 中最后的那个声明将会被应用到元素上。

当同一个元素有多个声明的时候,优先级才会有意义。因为每一个直接作用于元素的 CSS 规则总是会接管/覆盖(take over)该元素从祖先元素继承而来的规则。

下面列表中,选择器类型的优先级是递增的:

  1. 类型选择器和伪元素
  2. 类选择器,属性选择器和伪类
  3. ID 选择器

提示

给元素添加的内联样式 (例如,style="font-weight:bold") 总会覆盖外部样式表的任何样式 ,因此可看作是具有最高的优先级。

一个选择器的优先级可以说是由四个部分相加 (分量),可以认为是个十百千 — 四位数的四个位数:

  • 千位: 如果声明在 style 的属性(内联样式)则该位得一分。这样的声明没有选择器,所以它得分总是 1000。
  • 百位: 选择器中包含 ID 选择器则该位得一分。
  • 十位: 选择器中包含类选择器、属性选择器或者伪类则该位得一分。
  • 个位:选择器中包含元素、伪元素选择器则该位得一分。

注意

通配选择符*关系选择符 +,>,~,,||否定伪类 :not() 对优先级没有影响。但是,在 :not() 内部声明的选择器会影响优先级。

在进行计算时不允许进行进位,例如,20 个类选择器仅仅意味着 20 个十位,而不能视为 两个百位,也就是说,无论多少个类选择器的权重叠加,都不会超过一个 ID 选择器。

# !important 例外规则

当在一个样式声明中使用一个 !important 规则时,此声明将覆盖任何其他声明。虽然,从技术上讲,!important 与优先级无关,但它与最终的结果直接相关。

使用 !important 是一个坏习惯,应该尽量避免,因为这破坏了样式表中的固有的级联规则 使得调试找 bug 变得更加困难了。

当两条相互冲突的带有 !important 规则的声明被应用到相同的元素上时,拥有更大优先级的声明将会被采用。

一些经验法则:

  • 一定要优先考虑使用样式规则的优先级来解决问题而不是 !important
  • 只有在需要覆盖全站或外部 CSS 的特定页面中使用 !important
  • 永远不要在你的插件中使用 !important
  • 永远不要在全站范围的 CSS 代码中使用 !important

# :is():not() 例外规则

:not:is() 在优先级计算中不会被看作是伪类。但是,在计算选择器数量时还是会把其中的选择器当做普通选择器进行计数。

/* 选择器优先级:(0,0,2) */
/* main: (0,0,1) + div: (0,0,1) */
main:not(div) {
  background: unset;
}
1
2
3
4
5

# :where() 例外规则

实验功能优先级调整伪类::where()的优先级始终替换为零。

# 其他

# 关于 CSS 的执行效率:

  • 样式系统从最右边的选择符开始向左进行匹配规则。只要当前选择符的左边还有其他选择符,样式系统就会继续向左移动,直到找到和规则匹配的元素,或者因为不匹配而退出。
  • 如果你非常在意页面的性能那千万别使用 CSS3 选择器。实际上,在所有浏览器中,用 class 和 id 来渲染,比那些使用同胞,后代选择器,子选择器(sibling, descendant and child selectors)对页面性能的改善更值得关注。

Google 资深 web 开发工程师 Steve Souders 对 CSS 选择器的效率从高到低做了一个排序:

  1. id 选择器(#myid)
  2. 类选择器 (.myclassname)
  3. 标签选择器(div,h1,p)
  4. 相邻选择器(h1+p)
  5. 子选择器(ul < li)
  6. 后代选择器(li a)
  7. 通配符选择器(*)
  8. 属性选择器(a[rel="external"])
  9. 伪类选择器(a:hover,li:nth-child)

上面九种选择器中 ID 选择器的效率是最高,而伪类选择器的效率则是最低。

# 伪元素

  • E:first-line 匹配 E 元素的第一行
  • E:first-letter 匹配 E 元素的第一个字母
  • E:before 在 E 元素之前插入生成的内容
  • E:after 在 E 元素之后插入生成的内容

# 伪类

CSS 2.1 中的伪类

  • :first-child 匹配父元素的第一个子元素
  • :link 匹配所有未被点击的链接
  • :visited 匹配所有已被点击的链接
  • :active匹配鼠标已经其上按下、还没有释放的元素
  • :hover 匹配鼠标悬停其上的元素
  • :focus匹配获得当前焦点的元素
  • :lang(c) 匹配 lang 属性等于 c 的元素

CSS 3 中与用户界面有关的伪类

  • :enabled 匹配表单中激活的元素
  • :disabled 匹配表单中禁用的元素
  • :checked 匹配表单中被选中的 radio(单选框)或 checkbox(复选框)元素
  • ::selection 匹配用户当前选中的元素

CSS 3 中的结构性伪类

  • E:root 匹配文档的根元素,对于 HTML 文档,就是 HTML 元素
  • E:nth-child(n) 匹配其父元素的第 n 个子元素,第一个编号为 1
  • E:nth-last-child(n) 匹配其父元素的倒数第 n 个子元素,第一个编号为 1
  • E:nth-of-type(n):nth-child()作用类似,但是仅匹配使用同种标签的元素
  • E:nth-last-of-type(n):nth-last-child() 作用类似,但是仅匹配使用同种标签的元素
  • E:last-child匹配父元素的最后一个子元素,等同于:nth-last-child(1)
  • E:first-of-type 匹配父元素下使用同种标签的第一个子元素,等同于:nth-of-type(1)
  • E:last-of-type 匹配父元素下使用同种标签的最后一个子元素,等同于:nth-last-of-type(1)
  • E:only-child 匹配父元素下仅有的一个子元素,等同于:first-child:last-child:nth-child(1):nth-last-child(1)
  • E:only-of-type 匹配父元素下使用同种标签的唯一一个子元素,等同于:first-of-type:last-of-type:nth-of-type(1):nth-last-of-type(1)
  • E:empty 匹配一个不包含任何子元素的元素,注意,文本节点也被看作子元素

CSS 3 的反选伪类

:not(s)匹配不符合当前选择器的任何元素

CSS 3 中的 :target 伪类

:target 匹配文档中特定元素点击后的效果

# 属性选择器

  • [att] 匹配所有具有 att 属性的元素
  • [att=val] 匹配所有 att 属性等于"val"的元素
  • [att~=val] 匹配所有 att 属性具有多个空格分隔的值、其中一个值等于"val"的元素
  • [att|=val] 匹配所有 att 属性具有多个连字号分隔的值、其中一个值以"val"开头的元素
  • [att^="val"] 属性 att 的值以"val"开头的元素
  • [att$="val"] 属性 att 的值以"val"结尾的元素
  • [att*="val"] 属性 att 的值包含"val"字符串的元素

# 组合选择器

关系选择符(+, >, ~, ' ', ||)

  • ele + ele 兄弟选择器
  • ele > ele 子选择器
  • ele ~ ele 同级元素通用选择器,匹配任何在 E 元素之后的同级 F 元素
  • ele ele 后代选择器,通常用单个空格()字符表示
  • ele || ele 通过列合并符 (||)链接两个元素时, 它只会匹配被第二个 CSS 选择器匹配的元素,且此元素属于被第一个 CSS 选择器匹配的列元素。实验功能

# 参考文档:

上次编辑于: 2025年7月10日 04:01
贡献者: HugStars