CSS 选择器 & CSS 属性值计算 | 青训营笔记

209 阅读6分钟

这是我参与「第四届青训营 」笔记创作活动的第1天
本篇为青训营 CSS 课程,CSS 选择器相关 和 CSS 属性值计算过程 的笔记。

一、CSS 选择器

CSS 选择器的类型如下:

  • 通配符选择器 *

  • 标签选择器 tag

  • id 选择器 #id

  • class 选择器 .class

  • 属性选择器

    • [disabled]{}
    • input[type=“password”]{}
    • a[href^=“#”]{} ^=以某个字符串开头
    • a[href$=“.jpg”]{} $=以某个字符串结尾
    • a[href *= "facebook"]{} *=含有某个字符串
  • 伪类选择器

    • 状态伪类
      • :link
      • :visited
      • :hover
      • :active 鼠标按下后的状态
      • :focus
    • 结构性伪类(根据 DOM 元素)
      • :first-child
      • :last-child

CSS 选择器组合的结果及效果如下: image.png

二、CSS 属性值计算

简要说明如下,后文将进行详细解析:

  1. 首先会通过收集所有匹配的选择器的属性值(称为声明值),
  2. 如果有多个声明值,则会通过 CSS 来源、important、选择符的优先级以及书写顺序 依次比较,选择出最高优先级的属性值作为层叠值
  3. 如果没有声明值(则经过上一步骤没有层叠值),
    则此时会依情况使用继承值(属性能够继承,且其层叠链中对该属性有声明) 和默认值作为指定值
    经上一步骤有层叠值,则层叠值自动成为指定值
  4. 指定值中具有百分比、关键字等相对值,通过一定的计算将一部分的相对值 转换为 绝对值,得到计算值
    计算值中剩余的相对值为那些需要根据布局才能确定的属性
  5. 将计算值进一步转换得到 使用值
    此时所有的相对值都转换为了绝对值
    使用值中可能具有小数。但浏览器渲染不支持小数。
  6. 使用值中的小数化为整数,则得到实际值,即浏览器渲染时真正使用的值。
    至此,CSS 属性值计算完成。

CSS 属性计算的流程图如下: image.png

1.filtering -> 声明值

filtering:对应用到该页面的 CSS 规则用以下条件进行筛选:

  • 选择器匹配
  • 属性有效
  • 符合当前 media

得到 声明值
声明值 Declared Values:一个元素的某属性可能有 0 到多个声明值。

2、cascading -> 层叠值

Cascading:找出某个元素某个属性的所有 声明值,并选出优先级最高的一个属性值。
按照如下顺序选择优先级最高的:

  • 样式来源
  • 选择器特异度
  • 书写顺序

最终选出来的声明值 作为 层叠值


2.1 样式的来源:

  • 网页开发者的 CSS 样式表
  • 用户的浏览器设置(如最小字体大小 / 字体)
  • 浏览器的预设样式表

上述样式来源中,优先级是 开发者样式 最高, 浏览器内置样式 最低。
其中,在开发者样式中,内联样式 > 外部样式表 = 内部样式表

如果上述样式来源的属性都具有 !important,那么此时
!important 的浏览器内置样式 优先级最高,
!important 的开发者样式 最低。

image.png

2.2 选择器的特异度(Specificity)

  1. 计算选择符中 ID 选择器的个数 a
  2. 计算选择符中类选择器属性选择器以及伪类选择器的个数之和 b
  3. 计算选择符中 标签选择器伪元素选择器 的个数之和 c

按特异度 abc 的顺序依次比较大小,大的则优先级高,相等则比较下一个。
若最后两个的选择符的特异度 abc 都相等,则按照" 就近原则 "来判断:按照样式书写顺序,后面的优先级高。

3. Defaulting 默认值策略 -> 指定值

Defaulting:当层叠值为空的时候,使用继承或初始值作为 指定值

  • 属性可以继承,从父元素继承 计算值 作为指定值。
  • 属性不可继承,使用 初始值 作为指定值。

层叠值不为空时,即使用层叠值作为指定值
最终指定值一定不为空。

image.png

3.1 继承

  • 只有某些属性是可以继承的
  • 如果一直到根元素还没有继承到该属性,则使用初始值
  • CSS 中可以使用 inherit 显式从父级继承该属性的值

3.1.1 css可以继承的属性:

  1. 字体系列属性
    • font:组合字体
    • font-family:规定元素的字体系列
    • font-weight:设置字体的粗细
    • font-size:设置字体的尺寸
    • font-style:定义字体的风格
  2. 文本系列属性
    • text-indent:文本缩进
    • text-align:文本水平对齐
    • line-height:行高
    • word-spacing:字(单词)间隔
    • letter-spacing:字符间距
    • text-transform:控制文本大小写
    • direction:规定文本的书写方向
    • color:文本颜色
  3. 元素可见性:visibility
  4. 表格布局属性:
    • caption-side
    • border-collapse
    • border-spacing
    • empty-cells
    • table-layout
  5. 列表属性:
    • list-style-type
    • list-style-image
    • list-style-position
    • list-style
  6. 光标属性:cursor
初始值 对于 继承属性 与 非继承属性:
  • 对于继承属性,初始值只能用于没有指定值的根元素上
  • 对于非继承属性,初始值可以被用于没有指定值的任何元素上

允许使用 initial 关键词显式从父元素继承。

3.1.2 使 不可继承的属性(如 box-sizing)显式继承的方法:

  • 使用通配符选择器 * 将 不可继承属性 设置为:inherit 显式继承。
  • 为一个父级元素如 html 设置 该属性 为特定值,则该值会被其所有子元素显式继承。

image.png


3.2 初始值

  • 每个 CSS 属性都有一个规定的初始值。
  • 在层级链上没有找到的属性,会使用初始值。
  • 可以使用 initial 关键字显式设置为初始值。

4. Resolving -> 计算值

Resolving:将一些相对值或关键字转化为绝对值,得到 计算值

  • 将相对值转换成绝对值,如 em 转为 px
  • 处理特殊的值 inherit initial unset revert
  • 相对路径转为绝对路径

计算值 Computed Value:浏览器在不进行实际布局的情况下,能得到的最具体的值。

  • 有些元素的百分比值是相对于需要布局后才能知道的值:如widthmargin-righttext-indenttop
  • line-height 的属性值为不带单位的相对比值。

这些相对比值会在 使用值 确定后再被转换为绝对数值。

5.Formatting -> 使用值

Formatting:将计算值进一步转换,比如关键字、百分比等都转为绝对值,得到 使用值

  • 某些相对值无法单纯地通过 CSS 规则计算得出。如 body { width:90%; }
  • 实际进行布局的时候才能将这些值转化 为使用值

使用值 Used Value:进行文档布局使用的理论值,不会再有相对值或关键字。如400.2 px。
对于不依赖布局的 CSS 属性,其计算值与使用值一致。

解析值 Resolved ValueWindow.getComputedStyle() 返回的值。

  • 对于大多数属性,解析值等于其计算值
  • 对于一些旧属性,解析值等于 使用值

6. Constraining -> 实际值

Constraining:将小数像素值转为整数,得到实际值。

  • 计算出来的值受限制,需要经过处理
    • 小数点像素 -> 整数
    • 字体小于 12px
    • min-width / max-width 等

实际值 Actual Value: 渲染时实际生效的值,如 400 px。

参考

  1. CSS Cascade
  2. 聊聊css属性值的计算过程
  3. 刨根究底CSS(2):CSS中的各种值——初始值,就是默认值吗?