CSS基础-选择器与优先级
CSS选择器是前端开发的基础,理解选择器类型和优先级规则对于编写可维护的样式代码至关重要。
本文将系统介绍CSS选择器的各种类型、优先级计算规则以及实际应用中的最佳实践。
# 一、选择器类型
# 1.1 基础选择器
# 通配符选择器
* {
margin: 0;
padding: 0;
}
通配符选择器 * 匹配所有元素,常用于重置默认样式。但要注意性能问题,避免过度使用。
# 元素选择器
p {
color: #333;
line-height: 1.6;
}
h1 {
font-size: 2em;
font-weight: bold;
}
元素选择器直接使用HTML标签名,是最基础的选择器类型。
# 类选择器
.container {
width: 100%;
max-width: 1200px;
}
.btn-primary {
background-color: #007bff;
color: white;
}
类选择器使用 . 前缀,是实际开发中最常用的选择器,可复用性强。
# ID选择器
#header {
position: fixed;
top: 0;
width: 100%;
}
#main-content {
padding: 20px;
}
ID选择器使用 # 前缀,优先级最高,但不建议过度使用,因为会降低样式的可复用性。
# 1.2 组合选择器
# 后代选择器
/* 选择 .container 内所有的 p 元素 */
.container p {
margin-bottom: 1em;
}
/* 多层嵌套 */
nav ul li a {
text-decoration: none;
}
后代选择器使用空格分隔,匹配所有符合条件的后代元素,无论嵌套层级。
# 子选择器
/* 只选择直接子元素 */
.nav > li {
display: inline-block;
}
ul > li > a {
color: #333;
}
子选择器使用 > 符号,只匹配直接子元素,比后代选择器更精确。
# 相邻兄弟选择器
/* 选择紧跟在 h1 后面的 p 元素 */
h1 + p {
font-size: 1.2em;
color: #666;
}
相邻兄弟选择器使用 + 符号,只匹配紧邻的下一个兄弟元素。
# 通用兄弟选择器
/* 选择 h1 后面所有的 p 元素 */
h1 ~ p {
margin-left: 20px;
}
通用兄弟选择器使用 ~ 符号,匹配后面所有的兄弟元素。
# 1.3 属性选择器
# 基本属性选择器
/* 存在 title 属性 */
[title] {
cursor: help;
}
/* 完全匹配 */
[type="text"] {
border: 1px solid #ccc;
}
/* 包含特定词 */
[class~="btn"] {
padding: 5px 10px;
}
# 高级属性选择器
/* 以特定值开头 */
[href^="https"] {
color: green;
}
/* 以特定值结尾 */
[src$=".png"] {
border: 1px solid #ddd;
}
/* 包含特定字符串 */
[href*="example"] {
font-weight: bold;
}
/* 以特定值开头(包括连字符分隔) */
[lang|="zh"] {
font-family: "Microsoft YaHei";
}
# 1.4 伪类选择器
# 状态伪类
/* 链接状态 */
a:link { color: blue; }
a:visited { color: purple; }
a:hover { color: red; }
a:active { color: orange; }
/* 表单状态 */
input:focus {
border-color: #007bff;
outline: none;
}
input:disabled {
background-color: #f5f5f5;
cursor: not-allowed;
}
input:checked + label {
font-weight: bold;
}
# 结构伪类
/* 第一个/最后一个子元素 */
li:first-child {
margin-top: 0;
}
li:last-child {
border-bottom: none;
}
/* 唯一子元素 */
p:only-child {
margin: 0;
}
/* nth 选择器 */
tr:nth-child(odd) {
background-color: #f9f9f9;
}
tr:nth-child(even) {
background-color: #fff;
}
/* 每3个元素 */
li:nth-child(3n) {
color: red;
}
/* 从第4个开始 */
li:nth-child(n+4) {
display: none;
}
/* 前3个 */
li:nth-child(-n+3) {
font-weight: bold;
}
# 其他实用伪类
/* 非选择器 */
div:not(.special) {
opacity: 0.5;
}
/* 空元素 */
p:empty {
display: none;
}
/* 目标元素(锚点) */
:target {
background-color: yellow;
}
# 1.5 伪元素选择器
/* 首字母 */
p::first-letter {
font-size: 2em;
font-weight: bold;
float: left;
}
/* 首行 */
p::first-line {
color: #666;
}
/* 前后插入内容 */
.icon::before {
content: "→ ";
color: #007bff;
}
.external-link::after {
content: " ↗";
font-size: 0.8em;
}
/* 选中的文本 */
::selection {
background-color: #007bff;
color: white;
}
/* 占位符 */
input::placeholder {
color: #999;
font-style: italic;
}
# 二、选择器优先级
# 2.1 优先级计算规则
CSS优先级(特异性)通过四个数值来计算:(a, b, c, d)
- a: 内联样式(
style属性) = 1000 - b: ID选择器的数量 = 100
- c: 类选择器、属性选择器、伪类的数量 = 10
- d: 元素选择器、伪元素的数量 = 1
# 计算示例
/* (0, 0, 0, 1) = 1 */
p { }
/* (0, 0, 1, 0) = 10 */
.class { }
/* (0, 1, 0, 0) = 100 */
#id { }
/* (0, 0, 1, 1) = 11 */
p.class { }
/* (0, 1, 1, 1) = 111 */
#id .class p { }
/* (0, 2, 1, 0) = 210 */
#nav #menu .item { }
/* (1, 0, 0, 0) = 1000 */
<p style="color: red;"></p>
# 2.2 优先级比较规则
- 从左到右依次比较:先比较a,相同则比较b,以此类推
- !important 优先级最高:覆盖所有其他规则
- 相同优先级,后定义的覆盖先定义的
- 通配符选择器、组合器(+、>、~、空格)不增加优先级
/* 优先级: (0, 0, 1, 0) = 10 */
.text {
color: blue;
}
/* 优先级: (0, 1, 0, 0) = 100,会覆盖上面的规则 */
#content {
color: red;
}
/* 优先级: (0, 1, 1, 1) = 111,会覆盖上面的规则 */
#content .text p {
color: green;
}
/* !important 优先级最高 */
.text {
color: yellow !important; /* 最终生效 */
}
# 2.3 优先级实战案例
# 三、层叠规则(Cascade)
当多个规则应用于同一元素时,CSS使用以下顺序决定最终样式:
# 3.1 样式来源
CSS样式有三个来源,它们的优先级从低到高:
# 1. 用户代理样式(浏览器默认)
/* 浏览器内置的默认样式,例如: */
p {
display: block;
margin-block-start: 1em;
margin-block-end: 1em;
}
a {
color: blue;
text-decoration: underline;
}
这是浏览器自带的样式,优先级最低。
# 2. 用户样式(很少见)
用户通过浏览器设置或浏览器扩展自定义的样式,例如:
- 用户设置了更大的默认字体
- 用户安装了"夜间模式"扩展
- 无障碍辅助工具修改的样式
# 3. 作者样式(开发者编写)
/* 我们开发者写的CSS */
p {
margin: 0;
line-height: 1.6;
}
a {
color: #007bff;
text-decoration: none;
}
这是我们日常编写的样式,正常情况下优先级最高。
优先级顺序:
用户代理样式 < 用户样式 < 作者样式(开发者样式)
# 3.2 !important 的特殊性
当使用 !important 时,优先级顺序会反转:
作者样式!important < 用户样式!important < 用户代理样式!important
为什么会反转?
这是为了保护用户的选择权。例如:
- 用户因视力问题设置了
font-size: 20px !important - 开发者的样式不应该覆盖用户的无障碍需求
# 实际案例对比
<p class="text">这是一段文字</p>
场景1:没有!important
/* 用户代理样式(浏览器默认) */
p { color: black; }
/* 用户样式(用户设置) */
p { color: red; }
/* 作者样式(开发者编写) */
.text { color: blue; }
/* 结果:蓝色(作者样式优先级最高) */
场景2:使用!important
/* 作者样式(开发者编写) */
.text { color: blue !important; }
/* 用户样式(用户通过浏览器设置) */
p { color: red !important; }
/* 结果:红色(用户的!important优先级更高) */
# 3.3 完整的层叠优先级
综合考虑所有因素,完整的优先级从低到高:
- 用户代理样式(浏览器默认)
- 用户样式
- 作者样式(开发者编写)
- 作者样式 +
!important - 用户样式 +
!important - 用户代理样式 +
!important
# 3.4 同级别下的优先级判断
在同一来源的样式中,按以下规则判断:
- 优先级(特异性):按照前面介绍的规则计算
- 源码顺序:相同优先级时,后面的覆盖前面的
/* 示例:源码顺序的影响 */
.button {
background-color: blue;
color: white;
}
.button {
background-color: red; /* 会覆盖上面的蓝色 */
}
# 3.5 实用建议
在日常开发中:
- 用户代理样式:通常会用CSS Reset或Normalize.css重置
- 用户样式:基本不需要考虑,但要注意无障碍性
- 作者样式:我们主要关注这一层的优先级计算
- !important:尽量避免使用,除非确实需要覆盖第三方库样式
# 四、最佳实践
# 4.1 避免过度使用 !important
/* ❌ 不推荐 */
.button {
color: red !important;
}
/* ✅ 推荐:提高选择器优先级 */
.nav .button {
color: red;
}
# 4.2 保持选择器简洁
/* ❌ 不推荐:过于具体 */
body div.container ul li a.link {
color: blue;
}
/* ✅ 推荐:简洁明了 */
.nav-link {
color: blue;
}
# 4.3 使用类选择器而非ID选择器
/* ❌ 不推荐:难以复用 */
#header {
padding: 20px;
}
/* ✅ 推荐:可复用 */
.header {
padding: 20px;
}
# 4.4 合理使用组合选择器
/* ✅ 推荐:清晰的层级关系 */
.card > .card-header {
border-bottom: 1px solid #ddd;
}
.card .card-body p {
line-height: 1.6;
}
# 4.5 利用伪类减少类名
/* ❌ 不推荐 */
.list-item-first { }
.list-item-last { }
/* ✅ 推荐 */
.list-item:first-child { }
.list-item:last-child { }
# 4.6 使用属性选择器处理特殊情况
/* 外部链接添加图标 */
a[href^="http"]::after {
content: "↗";
margin-left: 4px;
}
/* PDF链接添加图标 */
a[href$=".pdf"]::before {
content: "📄 ";
}
# 五、调试技巧
# 5.1 使用浏览器开发者工具
- 查看计算后的样式(Computed)可以看到最终生效的属性
- 查看样式规则(Styles)可以看到被覆盖的规则(带删除线)
- 使用选择器过滤器快速定位样式来源
# 5.2 常见问题排查
问题1:样式不生效
- 检查选择器是否正确
- 检查优先级是否被覆盖
- 检查CSS语法是否正确
- 检查是否有缓存问题
问题2:优先级混乱
- 避免过度嵌套
- 减少ID选择器使用
- 统一命名规范(如BEM)
- 使用CSS预处理器管理
问题3:!important 滥用
- 重构选择器,提高优先级
- 调整CSS加载顺序
- 使用更具体的选择器
# 六、浏览器兼容性
现代浏览器对CSS选择器的支持已经非常完善:
| 选择器类型 | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| 基础选择器 | ✅ | ✅ | ✅ | ✅ |
| 伪类选择器 | ✅ | ✅ | ✅ | ✅ |
伪元素(::) | ✅ | ✅ | ✅ | ✅ |
| :not() | ✅ | ✅ | ✅ | ✅ |
| :nth-child() | ✅ | ✅ | ✅ | ✅ |
注意事项:
- IE11及以下版本对部分CSS3选择器支持不完善
- 伪元素推荐使用双冒号
::而非单冒号: - 使用Can I Use (opens new window)检查兼容性
# 七、总结
CSS选择器是构建网页样式的基础,掌握以下要点:
- 选择器类型:从基础到高级,灵活运用各种选择器
- 优先级计算:理解(a,b,c,d)四元组规则,避免优先级冲突
- 层叠规则:掌握来源、优先级、源码顺序的层叠逻辑
- 最佳实践:保持选择器简洁,避免!important,提高代码可维护性
- 调试技巧:善用开发者工具,快速定位样式问题
深入理解CSS选择器和优先级,能让你写出更优雅、更易维护的样式代码。
祝你变得更强!