1. CSS 选择器
在 MDN CSS 专栏中将CSS基本选择器分为了五类,分别是:
-
属性选择器 Attribute selectors: 通过已经存在的属性名或属性值匹配元素,
a [heref="www.baidu.com"] {}
-
类选择器 Class selectors: 根据该元素的类属性中的内容匹配元素,等价于属性选择器中的
[class ~= className]{}
-
ID选择器 ID selectors: 根据该元素的 ID 属性中的内容匹配元素,等价于属性选择器中的
[id = elementId]{}
-
元素选择器 Type selectors: 也称为类型选择器,通过 node 节点名称匹配元素,
div {}
-
通配选择器 Universal selectors: 用
*
来匹配任意类型的元素,与简单选择器配合可省略,*.div
等价于.div
除了这五类基本选择器外,常见的选择器还包括:
伪类选择器: 元素特定状态,
hover / active / focus
, 注意last-child
/only-child
也属于伪类-
伪元素选择器: 元素的特定部分,
before
/after
/placeholder
Tips:
- 在 CSS 3.0 中一个冒号表示伪类
:hover
两个冒号表示::after
伪元素,但是 CSS 2.0 中伪元素和伪类都是一个冒号(按照规范伪元素应该用::
,但为了保持兼容性,旧版本的 W3C 规范也适用,推荐都用一个冒号) - 并不是所有的元素都可以直接加伪元素,比如
<a>
标签就不能直接使用::first-letter
的伪元素,因为<a>
标签的默认display: inline
而::first-letter
只能应用于块级元素。
- 在 CSS 3.0 中一个冒号表示伪类
后代选择器: 空格,应用于符合条件的父元素下所有的匹配元素(子子孙孙),
div p
子代选择器: 大于号
>
,仅应用于符合条件的父子关系的元素(子),div > p
-
相邻兄弟选择器: 加号
+
,匹配指定关系的紧邻兄弟元素,第二个元素被选定,h1 + h2
=> 与h1
相邻且具有共同父元素的h2
Tips:
- 相邻兄弟选择器是顺序敏感的,
h1 + h2
必须h1
标签在前,h2
标签在后; - 所有的元素最终的父元素是 HTML body,直接在body下的元素互相也是兄弟元素,在选择器使用时需要注意影响面。
- 相邻兄弟选择器是顺序敏感的,
-
通用兄弟选择器: 波浪号
~
,匹配指定关系的所有同层级兄弟元素,h1 ~ h2
=> 与h1
具有共同父元素之后的所有同层级h2
Tips
- 通用兄弟选择器同样需要顺序明确
注意:选择器都可以组合使用, 如 h1 + h2 + h3
将会匹配拥有同样父元素的 h1, h2, h3
中的 h3
。
2. SASS中的父选择器 &
CSS的嵌套是最常见的写法,在SASS中为了书写避免重复的父元素样式,引入了父选择器&
,如SASS文件
a {
color: red;
&:after {
content: ">"
}
}
编译后
a {
color: red;
}
a:after {
content: ">";
}
TIPS
- 如果含有多层嵌套,最外层的父选择器会一层一层向下传递:
.container {
color: red;
&-button {
background: yellow;
&-icon {
font-size: large;
}
}
}
编译后
.container {
color: red;
}
.container-button {
background: yellow;
}
.container-button-icon {
font-size: large;
}
- 同一层级下的父选择器都是一样的:
.container {
color: red;
&-text {
color: blue;
}
&-button &-disabled {
background: yellow;
}
}
编译后
.container {
color: red;
}
.container-text {
color: blue;
}
.container-button .container-disabled {
background: yellow;
}
- 虽然叫父选择器,但他并不代表元素在HTML DOM的关系一定是父元素:
.container {
color: red;
.outer-container & {
color: blue;
}
}
编译后:
.container {
color: red;
}
.outer-container .container {
color: blue;
}
&
必须是选择器的第一个字符
.container {
color: red;
.outer-& & {
color: blue;
}
}
是无法编译的,但是可以写成:
.container {
color: red;
.&-outer & {
color: blue;
}
}
编译后成为:
.container {
color: red;
}
.container-outer .container {
color: blue;
}
虽然父选择器带来了便利,但是他也带来了一些麻烦:
- 元素类的命名可能存在大量重复
- 可能因为引用过多导致可阅读性较差
- 引用层级太深导致与DOM层级混乱
并不是用得越多越好,合理使用才是最佳。
3. 层叠与优先级
在HTML结构中元素之间肯定会存在层叠,但是我们其实并没有办法对于每个元素书写样式,所以CSS中存在样式的继承,具体可以看:MDN CSS 层叠与继承章节
本文主要针对层叠过后,多个样式选择器指向同一个元素的时候,CSS会采取如何的匹配原则。
首先,明确排序依据标准:
有三个因素需要考虑,根据重要性排序如下,后面的更重要:
- 资源顺序: 资源加载的先后
- 优先级: 需要一个标准的权重比例
- 重要程度:是否是极其重要,甚至可以无视其他样式
CSS 标准的权重计算公式:
一个选择器的优先级可以说是由三个不同的值(或分量)相加,可以认为是百(ID)十(类)个(元素)——三位数的三个位数:
- ID:选择器中包含 ID 选择器则百位得一分。
- 类:选择器中包含类选择器、属性选择器或者伪类则十位得一分。
- 元素:选择器中包含元素、伪元素选择器则个位得一分。
例子:
选择器 | ID (百) | 类(十) | 元素(个) | 优先级 |
---|---|---|---|---|
h1 |
0 | 0 | 1 | 0-0-1 |
h1 + h2::before |
0 | 0 | 3 | 0-0-3 |
#pwdContainer input |
1 | 0 | 1 | 1-0-1 |
div .container a:hover |
0 | 2 | 2 | 0-2-2 |
style="color: red" |
- | - | - | 1-0-0-0 |
!important |
- | - | - | TOP |
Tips: 伪类和伪元素的优先级不同,大部分伪类为0-1-0,伪元素则为0-0-1
总结:
!important > 内联样式 > ID选择器 > 类选择器(属性选择器、伪类选择器)> 元素选择器(伪元素选择器)> 其他选择器
Tips:
- 通用选择器(*)、子选择器(>)和相邻同胞选择器(+)并不在这四个等级中,所以它们的权值都为 0 ;
- 样式表的来源不同时,优先级顺序为:内联样式 > 内部样式 > 外部样式 > 浏览器用户自定义样式 > 浏览器默认样式;
- 继承得到的样式的优先级最低。