CSS 选择器
上一篇讲了 CSS 的属性,我们可以通过 CSS 的属性修饰 HTML 标签来达到某些效果,理论上有 CSS 的属性就可以了。但是为了提高 CSS 对标签修饰的效率,我们需要引用 CSS 选择器。比如,当页面上有多个列表,这些列表及列表的元素之间有相似之处,也有不同之处。如果你不使用 CSS 选择器的话,可以对每个列表及元素,使用单独的 CSS 属性来修饰,但是如果这样做,最后会发现有很多重复代码,代码也显得比较乱且臃肿。这个时候,你会想到将列表的相似部分抽象出来,进行统一修饰。这个时候就可以让 CSS 选择器来实现。这样一来,代码就会更清晰、简洁。这就是使用 CSS 选择器的重要原因。
1. CSS 选择器有哪些?
按照使用类型来分,CSS 选择器一共有 10类,分别是:
第 1 类:基本选择器
选择器类型 | 示例 | 说明 |
---|---|---|
通用选择器 | * | 匹配所有元素 |
标签选择器 | p | 匹配所有使用 p 标签的元素 |
ID 选择器 | #footer | 匹配所有 id 属性为 footer 的元素 |
类选择器 | .info | 匹配所有 class 属性为 info 的元素 |
第 2 类:层次选择器
不管是哪种选择器,选择器之间是可以进行组合使用的,而这些组合关系有四种:
选择器类型 | 示例 | 说明 |
---|---|---|
后代选择器 | div .left | 匹配 div 标签下 class 属性为 left 的所有元素,无论第几层 |
子选择器 | div>.left | 匹配 div 标签下第一层子元素中的 class 属性为 left 的元素 |
相邻兄弟选择器 | h4+p | 匹配 h4 标签相邻出现所有的 p 标签,且 h4 和 p 都有相同的父元素 |
通用兄弟选择器 | p~ul | 匹配 p 标签后面出现的所有 ul 标签,且 p 和 ul 都有相同的父元素 |
交集选择器 | div.left | 匹配 div 标签后面属性为 left 的元素,两个元素间没有空格 |
并集选择器 | div, .left, p | 匹配 div 标签,属性为 left 的元素以及 p 标签,元素间用逗号分隔 |
后代选择器与子选择器区的区别是:后代选择器会作用于父元素下所有的子元素,不管该元素是父元素的第几层。而子选择器,只会去父元素的第一层子元素中进行匹配。
后代选择器与通用兄弟选择器的区别是:后代选择器是匹配所有 “子元素”,而通用兄弟选择器是匹配元素后面所有 “同级元素” ,且两个元素有相同的父元素。
相邻兄弟选择器,需要注意的是从 + 号右边的元素才开始匹配。比如:li+li,所以第一个 li 是不匹配的。
通用兄弟选择器与相邻兄弟选择器的区别是:通用兄弟选择器忽略 “相邻” 这个规则。
另外,子选择器两个元素之间不是严格的 “父子关系”,子元素的定义则不会生效。
第 3 类:伪类选择器
选择器类型 | 示例 | 说明 |
---|---|---|
链接伪类选择器 | a:link | 匹配所有 a 元素,定义匹配元素的超链接未被访问过的属性 |
链接伪类选择器 | a:visited | 匹配所有 a 元素,定义匹配元素的超链接已被访问过的属性 |
用户行为伪类选择器 | a:active | 匹配所有 a 元素,定义匹配元素被激活时的属性 |
用户行为伪类选择器 | a:hover | 匹配所有 a 元素,定义匹配元素当用户鼠标停留在元素 E 上的属性 |
用户行为伪类选择器 | input:focus | 匹配所有 input 元素,定义匹配元素当 E 元素获得焦点时的属性 |
目标伪类选择器 | p:target | 匹配所有 a 元素,定义匹配元素被相关 URL 指向内容的属性 |
选中状态伪类选择器 | input:checked | 匹配所有 input 元素,定义表单元素(通常是单选或复选按钮)被选中时的属性 |
启用状态伪类选择器 | input:enabled | 匹配所有 input 元素,定义表单元素启用时的属性 |
不可用状态伪类选择器 | input:disabled | 匹配所有 input 元素,定义表单元素禁用时的属性 |
结构伪类选择器 | E:first-child | 匹配所有 E 元素,并找到其父元素,设置所有父元素的第一个元素的属性 |
结构伪类选择器 | E:last-child | 匹配所有 E 元素,并找到其父元素,设置所有父元素的最后一个元素的属性 |
结构伪类选择器 | E:root | 匹配元素 E 的根元素属性。在 HTML 文档中,根元素始终是 <html>,此时该选择器与 <html> 类型选择器匹配的内容相同 |
结构伪类选择器 | E:nth-child(n) | 匹配所有 E 元素,并找到其父元素,设置父元素的第 n 个元素的属性 |
结构伪类选择器 | E:nth-last-child(n) | 匹配所有 E 元素,并找到其父元素,设置父元素的倒数第 n 个元素的属性 |
结构伪类选择器 | E:nth-of-type(n) | 匹配所有 E 元素,并找到其父元素,设置父元素中同类 E 元素中的第 n 个元素的属性 |
结构伪类选择器 | E:nth-last-of-type(n) | 匹配所有 E 元素,并找到其父元素,设置父元素中同类 E 元素中倒数第 n 个元素的属性 |
结构伪类选择器 | E:first-of-type | 相当于 E:nth-of-type(1) |
结构伪类选择器 | E:last-of-type | 相当于 E:nth-last-of-type(1) |
结构伪类选择器 | E:only-child | 匹配所有 E 元素,并找到其父元素中只有一个子元素的父元素,设置该子 元素(E 元素)的属性 |
结构伪类选择器 | E:only-of-type | 匹配所有 E 元素,并找到其父元素中唯一类型的子元素,设置该子元素的属性 |
结构伪类选择器 | E:empty | 匹配所有 E 元素,并找到这些元素中没有子元素的 E 元素,设置该 E 元素的属性 |
否定伪类选择器 | :not(E) E:not(F) |
:not(E) 匹配所有非 E 元素,设置这些元素的属性 E:not(F) 在 E 元素中,找到所有非 F 的元素(含 E 在内),并设置这些元素的属性 |
第 4 类:伪元素选择器
伪元素特性:
- 它不存在于文档中,所以 JS 无法操作它
- 它属于主元素本身,有些伪类仅仅是代表元素内容的一部分,譬如 :first-letter 代表第一个字母;因此当伪元素被点击的时候触发的是主元素的 click 事件
- 块级元素才能有 :before, :after,譬如 img 就不能设置,亦即某些元素是没有 :before, :after 的,只要知道一般的块级元素都可以用就行了
CSS3 中,为了与伪类区分,伪元素前应该使用两个冒号,即 :hover 伪类,::before 伪元素。当然为了向下兼容,用一个冒号也是可以的,不过建议尽量使用规范的写法。
属性 | 描述 |
---|---|
:first-letter | 向文本的第一个字母添加特殊样式 |
:first-line | 向文本的首行添加特殊样式 |
:before | 在元素之前添加内容 |
:after | 在元素之后添加内容 |
第 5 类:属性选择器
属性 | 描述 |
---|---|
[attribute] | 匹配含有 attribute 属性的元素 |
[attribute=value] | 匹配含有 attribute 属性,且属性值等于 "value" 的元素 |
[attribute~=value] | 匹配含有 attribute 属性,且属性值中含有 “value" 的元素 |
[attribute=value] | 匹配含有 attribute 属性,且属性值以 "value" 开头的元素,该值必须是整个单词 |
[attribute^=value] | 匹配含有 attribute 属性,且属性值以 "value" 开头的元素,不需要是整个单词 |
[attribute$=value] | 匹配含有 attribute 属性,且属性值以 "value" 结尾的元素,不需要是整个单词 |
[attribute*=value] | 匹配含有 attribute 属性,且属性值包含 "value" 的元素,不论其所在位置 |
需要注意的是,value 在元素中的属性值都是 “字符串”,需要用双引号引起来,但在写选择器的时候,却不需要双引用。
2. CSS 选择器的优先级
上面这些不同类型的选择器优先级规则如下:
-
内联 (行内) 样式 > ID 选择器 > 类选择器 = 属性选择器 = 伪类选择器 > 标签选择器 = 伪元素选择器
-
如果遇到同一级的选择器,那么:最近的祖先样式比其他祖先样式优先级高。如:
<!-- 类名为 son 的 div 的 color 为 blue -->
<div style="color: red">
<div style="color: blue">
<div class="son"></div>
</div>
</div>
另外,"直接(行内)样式"比"祖先样式"优先级高。如:
<!-- 类名为 son 的 div 的 color 为 blue -->
<div style="color: red">
<div class="son" style="color: blue"></div>
</div>
- 属性后插有 !important 的属性拥有最高优先级。
p {
background: red !important;
}
.father .son {
background: blue;
}
<div class="father">
<p class="son"></p>
</div>
- 选择器组合时的优先级判断,通常我们用1表示标签选择器的优先级,10 表示类选择器的优先级,100 标示 ID 选择器的优先级。比如:
.polaris #xxx {color: blue};
.polaris span {color: red};
.polaris span {color:red;} 的选择器优先级是 10 + 1 也就是11,而 .polaris #xxx 的优先级是110。如果某元素受到两种选择器的影响,那么最终元素会被优先级高的选择器修饰。
3. 如何提升 CSS 选择器性能?
-
避免使用通用选择器
-
避免使用标签或类选择器来限制 ID 选择器
// 不好的写法
button#backButton {…}
.menu-left#newMenuIcon {…}
// 好的写法
#backButton {…}
#newMenuIcon {…}
-
避免使用标签选择器来限制类选择器
-
避免使用多层标签选择器,使用类选择器替换,减少 CSS 查找
-
避免使用子选择器
-
使用继承
4. 简洁、高效的 CSS
-
不要在ID选择器前使用标签名,ID 选择器是唯一的,加上标签名反而增加不必要的匹配
-
不要在类选择器前使用标签名,除非你在不同标签下定义了同名的类选择器
-
尽量少使用层级关系,如果要使用层级关系尽量使用类选择器表示
以上参考
- https://www.w3school.com.cn/cssref/css_selectors.asp
- https://www.w3cschool.cn/css3/css3-selector.html
- https://www.w3cschool.cn/css/css-selector.html
- https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Getting_started/Selectors
- http://www.ruanyifeng.com/blog/2009/03/css_selectors.html
- https://www.runoob.com/w3cnote/css-style-priority.html