CSS 优先级浅析

前言

层叠样式表 CSS 做为 Web 重要组成部分,开发人员的关注点大多在于复杂的视觉效果、惆怅的浏览器兼容性、脆弱的可维护性,而对于最基本的层叠优先级规则,每每如同雾里看花,人云亦云,甚至产生原则性谬误,本文基于规范文档,尝试理清脉络。css

层叠样式

所谓层叠,跳过晦涩定义,简单理解为,浏览器为特定元素,不一样来源的属性声明,选择优先级最高的终值。html

优先级排序依次以下:web

Origin and Importance

规则声明来源(Origin)分为如下部分:chrome

  • user agent declarations - 浏览器预设样式
  • user declarations - 用户手动预设样式,部分浏览器不支持
  • author declarations - 开发人员设定样式
  • Animation - 动画插帧
  • Transition - 过渡效果插帧

Importance 暨使用关键字 !important 声明规则。浏览器

优先级排序以下:网络

  1. Transition declarations
  2. Important user agent declarations
  3. Important user declarations
  4. Important author declarations
  5. Animation declarations
  6. Normal author declarations
  7. Normal user declarations
  8. Normal user agent declarations

通常状况下,仅考虑浏览器预设样式,开发者设定样式便可,终端用户样式不归入考虑。动画

Scope

经过 scoped style element 声明的样式,仅对其父元素范围内生效。若是存在嵌套关系,优先级顺序以下:ui

  1. Important ansestor declarations
  2. Important descendant declarations
  3. Normal descendant declarations
  4. Normal ansestor declarations

unscoped declarations 能够理解做用域为 root elementstyle attribute declarations 能够理解做用域为元素自己,style attribute important declarations 理解做用域为 root elementspa

<div class="outer">
  <style scoped> .success { color: purple; } </style>
  <ul class="base">
    <li class="success">success</li>
    <li class="success">success</li>
    <li class="success">success</li>
  </ul>
  <div class="inner">
    <style scoped> .success { color: yellow; } </style>
    <ul class="base">
      <li class="success">success</li>
      <li class="success">success</li>
      <li class="success">success</li>
    </ul>
  </div>
</div>
复制代码

示例代码 .success 大几率所有为黄色,由于规范已删除 scoped css,大部分浏览器已不支持。顺便一提,经过工程化手段可以实现相似的功能。code

原始代码:

<style scoped> .example { color: red; } </style>

<template>
  <div class="example">hi</div>
</template>
复制代码

转换后代码:

<style> .example[data-v-f3f3eg9] { color: red; } </style>

<template>
  <div class="example" data-v-f3f3eg9>hi</div>
</template>
复制代码

Specificity

选择器的特异性由选择器自己的成分肯定,计算规则以下:

  • 计数选择器中 ID 选择器数量 A
  • 计数选择器中类选择器、属性选择器、伪类选择器数量 B
  • 计数选择器中元素原则器、伪元素选择器数量 C

选择器特异性标记记为:

P(S)=
  \begin{pmatrix}
  A & B & C \\
  \end{pmatrix}

比较时,按从左至右方向比较。

特殊场景须要特别注意:

  • 伪类选择器 :is():not():has() 特异性为参数选择器列表中,特异性最高的选择器特异性
  • 伪类选择器 :nth-child(An+B [of S]?):nth-last-child(An+B [of S]?) 特异性为参数选择器列表中,特异性最高的选择器特异性叠加普通伪类选择器特异性
  • 伪类选择器 :where() 特异性为 0
  • 通配选择器 * 特异性为 0

举例说明:

选择器 特异性
#container .header (1, 1, 0)
#container section (1, 0, 1)
.container *:not(.header) (0, 2, 0)

Order of Appearance

位置靠后的样式声明优先级更高,包含两点:

  • 单文件内样式声明顺序
  • 多文件 @import()<style><link> 引入前后顺序

扩展思考

理论基本介绍完毕,将理论应用于实践才是最终目的。

四参数比较法

选择器优先级,可能看到的四参数版本:

  • 行内样式声明标志位计为 A
  • 计数选择器中 ID 选择器数量 B
  • 计数选择器中类选择器、属性选择器、伪类选择器数量 C
  • 计数选择器中元素原则器、伪元素选择器数量 D
A =
\begin{cases}
1,  & \text{行内样式} \\
0, & \text{非行内样式}
\end{cases}

比较时,按从左至右方向比较:

P(S)=
  \begin{pmatrix}
  A & B & C & D \\
  \end{pmatrix}

延伸出加权取和比较法:

P(S) = 1000 \times A + 100 \times B + 10 \times C + D

问题:如何看待这种比较方式

自动填充

部分浏览器支持表单自动填充,默认状况下,填充后的输入框样式较为丑陋,且与总体风格不搭,默认的效果基本以下(图来自网络):

Chrome 78 样式声明以下:

input:-internal-autofill-selected {
  background-color: rgb(232, 240, 254) !important;
  background-image: none !important;
  color: rgb(0, 0, 0) !important;
}
复制代码

Safari 13 样式声明以下:

input:-webkit-autofill,
input:-webkit-autofill-strong-password {
  background-color: rgb(250, 255, 189);
  background-image: none;
  color: rgb(0, 0, 0);
}
复制代码

问题:如何处理浏览器预设丑不拉几的自动填充效果?

其它

  • 如何覆盖依赖库引入的样式?
  • 如何避免复杂的优先级计算?
  • 如何在多人协做项目中维护样式?

参考连接

相关文章
相关标签/搜索