这是我参与「第五届青训营 」伴学笔记创作活动的第1天。
今天学习了CSS选择器优先级的计算,非常详细,要牢记心中。
浏览器渲染流程
- 构建DOM树(parse):解析HTML,生成DOM树,解析CSS, 生成CSSOM树。
- 构建渲染树(construct):将DOM树和CSSOM树结合,生成渲染树(Render Tree)。
- 布局渲染树(reflow/layout):根据生成的渲染树,计算它们在设备视口(viewport)内的确切位置和大小,这个计算的阶段就是回流。
- 绘制渲染树(paint/repaint):根据渲染树的以及回流得到的几何信息,得到节点的绝对像素。
- Display:将像素发送给GPU,展示在页面上。
CSS选择器是我们在项目开发中常用的工具。CSS既然是层叠样式表,那样式就是层层叠叠地覆盖html中的元素。那被不同的样式选中的元素,要展示哪个样式就涉及到选择器的权重的问题,权重更高的样式覆盖权重低的样式。
选择器
- 简单选择器(Simple selectors):通过元素类型(直接选)、class (.)或 id (#)匹配一个或多个元素。
- 属性选择器(Attribute selectors):通过属性 / 属性值 匹配一个或多个元素。
- 伪类(Pseudo-classes):匹配处于确定状态的一个或多个元素,比如被鼠标指针悬停的元素,或当前被选中或未选中的复选框,或元素是 DOM 树中一父节点的第一个子节点。以一个冒号(:)为前缀。
- 伪元素(Pseudo-elements):匹配处于相关的确定位置的一个或多个元素,例如每个段落的第一个字,或者某个元素之前生成的内容。以两个冒号(::)为前缀。伪类和伪元素的差别:每个选择器最多只能使用一个伪元素,每个选择器可以使用多个伪类。
- 组合器(Combinators):这里不仅仅是选择器本身,还有以有效的方式组合两个或更多的选择器用于非常特定的选择的方法。例如,你可以只选择 divs 的直系子节点的段落,或者直接跟在 headings 后面的段落。
| Combinators | Select |
|---|---|
| A,B | 匹配满足A(和/或)B的任意元素. |
| A B | 匹配任意元素,满足条件:B是A的后代结点(B是A的子节点,或者A的子节点的子节点) |
| A > B | 匹配任意元素,满足条件:B是A的直接子节点 |
| A + B | 匹配任意元素,满足条件:B是A的下一个兄弟节点(AB有相同的父结点,并且B紧跟在A的后面) |
| A ~ B | 匹配任意元素,满足条件:B是A之后的兄弟节点中的任意一个(AB有相同的父节点,B在A之后,但不一定是紧挨着A) |
- 多用选择器(Multiple selectors):这些也不是单独的选择器;这个思路是将以逗号分隔开的多个选择器放在一个 CSS 规则下面, 以将一组声明应用于由这些选择器选择的所有元素。
优先级计算
!important- 内联样式/行内样式 (1000)
- ID选择器(0100)
- 类选择器/属性选择器/伪类选择器(0010)
- 元素选择器/伪元素选择器(0001)
- 关系选择器/通配符选择器(0000)
带!important 标记的样式属性优先级最高; 样式表的来源相同时: !important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
每一个选择器都能计算出一个【权重值】话语权,格式为:(a,b,c)
a表示:一个选择器中【ID】选择器的个数。
b表示:一个选择其中【类、伪类、属性】选择器的个数。
c表示:一个选择其中【元素、伪元素】选择器的个数。
权重值是逐位比较,计算权重来决定使用哪个样式。(同等权重的时候后来者居上)
/* 第一种写法 权重(0,2,3)*/
div.earthy ul.list li{
color:red;
}
/* 第二种写法 权重(0,1,3)*/
.earthy>ul[a="hello"]>li {
color:blue;
}
/* 第三种写法 权重(0,2,2)*/
.earthy ul[a="hello"]>li{
color:green;
}
/* 第四种写法 权重(0,2,3)*/
body .earthy ul[a="hello"]>li{
color:pink;
}
总结
今天说清楚了优先级计算的方法,希望牢记顺序以及各个选择器包含哪些内容。