CSS 优先级
1. 概念
CSS 优先级(Specificity) 是指当多个样式规则应用于同一个元素时,浏览器决定哪个样式生效的规则。
优先级是 CSS 层叠性的核心机制之一,它决定了样式冲突时的最终效果。
2. 优先级计算规则
2.1 权重值系统
| 选择器类型 | 权重值 | 说明 |
|---|---|---|
| !important | ∞ (无穷大) | 最高优先级,慎用 |
| 内联样式 | 1000 | <div style=""> |
| ID 选择器 | 100 | #header |
| 类选择器 | 10 | .container |
| 属性选择器 | 10 | [type="text"] |
| 伪类选择器 | 10 | :hover, :focus |
| 标签选择器 | 1 | div, p |
| 伪元素选择器 | 1 | ::before, ::after |
| 通配符选择器 | 0 | * |
| 关系选择器 | 0 | +, >, ~, (空格) |
2.2 优先级计算示例
/* 权重: 1 */
div { color: red; }
/* 权重: 10 */
.box { color: blue; }
/* 权重: 11 (10 + 1) */
div.box { color: green; }
/* 权重: 100 */
#header { color: orange; }
/* 权重: 110 (100 + 10) */
#header.active { color: purple; }
/* 权重: 111 (100 + 10 + 1) */
#header.active a { color: pink; }
/* 权重: 20 (10 + 10) */
.nav.active { background: blue; }
/* 权重: 21 (10 + 10 + 1) */
.nav.active ul { background: green; }3. 优先级计算方法
3.1 三位数表示法
将优先级表示为 (A, B, C) 三位数:
- A: ID 选择器数量
- B: 类选择器、属性选择器、伪类选择器数量
- C: 标签选择器、伪元素选择器数量
计算示例
/* (0, 0, 1) = 1 */
div { }
/* (0, 1, 0) = 10 */
.box { }
/* (0, 1, 1) = 11 */
div.box { }
/* (1, 0, 0) = 100 */
#header { }
/* (1, 1, 0) = 110 */
#header.active { }
/* (1, 1, 1) = 111 */
#header.active a { }
/* (0, 2, 1) = 21 */
.nav.active ul { }3.2 比较规则
- 先比较 A (ID 选择器数量)
- 如果 A 相同,比较 B (类选择器数量)
- 如果 B 相同,比较 C (标签选择器数量)
- 如果全部相同,后面的覆盖前面的
比较示例
/* (0, 1, 1) = 11 */
div.box { color: red; }
/* (1, 0, 0) = 100 ✓ 更高优先级 */
#header { color: blue; }
/* 结果: 蓝色生效 */
---
/* (0, 2, 0) = 20 */
.nav.active { color: red; }
/* (0, 1, 1) = 11 */
div.box { color: blue; }
/* 结果: 红色生效 (20 > 11) */
---
/* (1, 1, 0) = 110 */
#header.active { color: red; }
/* (1, 1, 1) = 111 ✓ 更高优先级 */
#header.active a { color: blue; }
/* 结果: 蓝色生效 (111 > 110) */4. 特殊情况
4.1 !important 优先级
/* 普通 */
#header { color: red; } /* 权重: 100 */
/* !important 覆盖一切 */
.container { color: blue !important; } /* 权重: 10,但 !important 生效 */
/* 结果: 蓝色生效 */注意:
- !important 会破坏正常的层叠性,应尽量避免使用
- 如果多个样式都有 !important,则按照普通优先级规则比较
4.2 相同优先级,后覆盖前
/* 权重相同: 10 */
.box { color: red; }
.box { color: blue; } /* 后面的覆盖前面的 */
/* 结果: 蓝色生效 */4.3 内联样式优先级
<style>
.box { color: red; } /* 权重: 10 */
</style>
<div class="box" style="color: blue"> <!-- 权重: 1000 -->
这段文字是蓝色
</div>
<!-- 结果: 内联样式生效 -->4.4 继承的样式优先级最低
<style>
body { color: red; } /* 继承的样式 */
div { color: blue; } /* 权重: 1,但覆盖继承的红色 */
</style>
<body>
<div>这段文字是蓝色</div>
</body>
<!-- 结果: 蓝色生效,直接设置的样式优先级高于继承 -->5. 选择器组合的优先级
5.1 后代选择器
/* 权重: 2 (1 + 1) */
div p { color: red; }
/* 权重: 11 (10 + 1) */
div .box { color: blue; }
/* 权重: 12 (1 + 10 + 1) */
div .box p { color: green; }
/* 权重: 101 (100 + 1) */
#header p { color: orange; }5.2 子代选择器
/* 权重: 2 (1 + 1) */
div > p { color: red; }
/* 权重: 11 (10 + 1) */
div > .box { color: blue; }
/* 权重: 12 (1 + 10 + 1) */
div > .box > p { color: green; }注意: 子代选择器 > 和后代选择器 (空格) 的权重计算方式相同,关系选择器本身不增加权重。
5.3 兄弟选择器
/* 权重: 2 (1 + 1) */
div + p { color: red; }
/* 权重: 11 (10 + 1) */
.box + a { color: blue; }
/* 权重: 2 (1 + 1) */
div ~ p { color: green; }5.4 伪类和伪元素
/* 权重: 11 (10 + 1) */
a:hover { color: red; }
/* 权重: 2 (1 + 1) */
p::before { content: ''; }
/* 权重: 12 (10 + 1 + 1) */
.box:hover span { color: blue; }
/* 权重: 20 (10 + 10) */
.box.active { color: green; }5.5 属性选择器
/* 权重: 10 */
input[type="text"] { }
/* 权重: 10 */
a[href^="http"] { }
/* 权重: 10 */
div[data-id="123"] { }
/* 权重: 20 (10 + 10) */
input[type="text"]:focus { }6. 实战应用
应用 1: 按钮样式系统
/* 基础按钮 - 权重: 10 */
.btn {
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* 大按钮 - 权重: 20 (10 + 10) */
.btn.btn-lg {
padding: 15px 30px;
font-size: 1.2em;
}
/* 小按钮 - 权重: 20 */
.btn.btn-sm {
padding: 5px 15px;
font-size: 0.9em;
}
/* 主题按钮 - 权重: 20 */
.btn.btn-primary {
background: #007bff;
}
/* 成功按钮 - 权重: 20 */
.btn.btn-success {
background: #28a745;
}
/* 危险按钮 - 权重: 20 */
.btn.btn-danger {
background: #dc3545;
}
/* 禁用状态 - 权重: 20 */
.btn.disabled {
background: #ccc;
cursor: not-allowed;
pointer-events: none;
}应用 2: 导航栏样式
/* 导航容器 - 权重: 10 */
.nav {
display: flex;
background: #333;
padding: 0 20px;
}
/* 导航链接 - 权重: 11 (10 + 1) */
.nav a {
display: block;
padding: 15px;
color: white;
text-decoration: none;
transition: background 0.3s;
}
/* 悬停效果 - 权重: 11 */
.nav a:hover {
background: rgba(255, 255, 255, 0.1);
}
/* 激活状态 - 权重: 20 (10 + 10) */
.nav a.active {
background: #007bff;
font-weight: bold;
}
/* 禁用链接 - 权重: 20 */
.nav a.disabled {
color: #999;
pointer-events: none;
}应用 3: 表单样式
/* 表单输入框 - 权重: 11 (10 + 1) */
.form-input {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
/* 聚焦状态 - 权重: 11 */
.form-input:focus {
outline: none;
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
}
/* 错误状态 - 权重: 20 (10 + 10) */
.form-input.error {
border-color: #dc3545;
background: #fff5f5;
}
/* 成功状态 - 权重: 20 */
.form-input.success {
border-color: #28a745;
background: #f5fff5;
}
/* 必填标记 - 权重: 22 (10 + 10 + 1 + 1) */
.form-input.required:focus::placeholder {
color: #dc3545;
}应用 4: 卡片组件
/* 卡片 - 权重: 10 */
.card {
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
/* 卡片标题 - 权重: 11 (10 + 1) */
.card-title {
padding: 20px;
font-size: 1.5em;
font-weight: bold;
border-bottom: 1px solid #eee;
}
/* 卡片内容 - 权重: 11 */
.card-body {
padding: 20px;
line-height: 1.6;
color: #666;
}
/* 卡片底部 - 权重: 11 */
.card-footer {
padding: 20px;
border-top: 1px solid #eee;
background: #f9f9f9;
}
/* 带边框的卡片 - 权重: 20 */
.card.bordered {
border: 1px solid #ddd;
box-shadow: none;
}
/* 主要卡片 - 权重: 20 */
.card.primary {
border: 2px solid #007bff;
}7. 优先级调试技巧
7.1 浏览器开发者工具
- 打开开发者工具 (F12)
- 选择元素 (点击元素或使用 Ctrl+Shift+C)
查看 Styles 面板
- 显示所有应用的选择器
- 被划掉的样式表示被覆盖
- 按优先级从高到低排序
查看 Computed 面板
- 显示最终生效的样式
- 可以追溯到样式来源
7.2 使用注释记录权重
/* 权重: 10 */
.box { }
/* 权重: 100 */
#container { }
/* 权重: 20 (10 + 10) */
.nav.active { }
/* 权重: 111 (100 + 10 + 1) */
#header.main a { }7.3 添加调试样式
/* 调试: 高亮显示元素 */
.debug {
border: 2px solid red !important;
background: yellow !important;
}
/* 查看优先级 */
.test {
color: red; /* 权重: 10 */
color: blue !important; /* 权重: ∞ - 覆盖 */
}8. 注意事项
8.1 避免过高优先级
/* ❌ 不推荐: 过高的优先级,难以覆盖 */
.container .sidebar .widget .title {
color: red; /* 权重: 30 (0, 3, 0) */
}
/* ✅ 推荐: 合理的优先级 */
.widget-title {
color: red; /* 权重: 10 (0, 1, 0) */
}8.2 避免 ID 选择器
/* ❌ 不推荐: ID 选择器优先级过高 */
#header {
background: blue;
}
#header .nav {
color: white; /* 需要更高优先级才能覆盖 */
}
/* ✅ 推荐: 使用类选择器 */
.header {
background: blue;
}
.header .nav {
color: white; /* 容易覆盖 */
}8.3 慎用 !important
/* ❌ 不推荐: 滥用 !important */
.one .two .three .text {
color: red !important;
}
.another .text {
color: blue !important; /* 只能用 !important 覆盖 */
}
/* ✅ 推荐: 优化选择器 */
.highlight-text {
color: red;
}
.secondary-text {
color: blue; /* 正常覆盖 */
}8.4 保持选择器简洁
/* ❌ 不推荐: 过度复杂的选择器 */
div ul li a span.highlight {
color: red; /* 权重: 14 (0, 1, 3) */
}
/* ✅ 推荐: 简洁的选择器 */
.highlight {
color: red; /* 权重: 10 (0, 1, 0) */
}9. 常见问题解答
Q1: 为什么我的样式不生效?
A: 检查:
- 选择器是否正确
- 优先级是否足够
- 是否被其他更高优先级的样式覆盖
- 是否有语法错误
- 使用开发者工具查看
Q2: 何时应该使用 !important?
A: 仅在以下情况使用:
- 需要覆盖第三方库样式
- 紧急修复(临时方案)
- 打印样式覆盖
- 用户自定义样式
Q3: 如何计算复杂选择器的优先级?
A:
- 统计 ID 选择器数量 (A)
- 统计类、属性、伪类选择器数量 (B)
- 统计标签、伪元素选择器数量 (C)
- 比较 (A, B, C) 三位数
Q4: 继承的样式优先级是多少?
A: 继承的样式优先级最低,低于任何直接设置的样式,即使直接设置的样式权重为 0。
Q5: 同优先级时,怎么决定哪个生效?
A:
- 后面的覆盖前面的
- 如果是不同 CSS 文件,后引入的覆盖先引入的
- 内联样式 > 内部样式 > 外部样式(同优先级时)
10. 最佳实践
10.1 选择器优先级策略
/* 1. 使用类选择器为主 */
.card { }
.btn { }
.nav { }
/* 2. 组合类选择器提高优先级 */
.card.primary { }
.btn.active { }
.nav.main { }
/* 3. 避免使用 ID 选择器 */
/* ❌ #header { } */
/* ✅ .header { } */
/* 4. 保持选择器简洁 */
/* ❌ div ul li a { } */
/* ✅ .nav-link { } */10.2 CSS 架构建议
/* 1. 重置样式 */
* { margin: 0; padding: 0; }
/* 2. 基础样式 (低优先级) */
body { font-size: 16px; }
a { color: #007bff; }
/* 3. 组件样式 (中优先级) */
.card { }
.btn { }
/* 4. 修饰符 (中优先级) */
.card.primary { }
.btn.large { }
/* 5. 状态样式 (中优先级) */
.btn:hover { }
.btn.active { }
/* 6. 页面样式 (高优先级) */
.home-page .hero { }
.about-page .content { }
/* 7. 紧急修复 (!important - 慎用) */
.error { color: red !important; }10.3 命名规范
/* BEM 命名法 */
.block { } /* 块 */
.block__element { } /* 元素 */
.block--modifier { } /* 修饰符 */
/* 示例 */
.card { }
.card__title { }
.card__body { }
.card--primary { }
.card--bordered { }11. 总结
CSS 优先级关键要点:
权重系统:
- !important: ∞
- 内联样式: 1000
- ID 选择器: 100
- 类/属性/伪类: 10
- 标签/伪元素: 1
- 通配符/关系: 0
计算方法:
- 表示为 (A, B, C) 三位数
- A: ID 数量
- B: 类/属性/伪类数量
- C: 标签/伪元素数量
比较规则:
- 先比 A,再比 B,最后比 C
- 相同优先级,后覆盖前
- !important 优先级最高
注意事项:
- 避免过高优先级
- 慎用 ID 选择器
- 慎用 !important
- 保持选择器简洁
最佳实践:
- 使用类选择器为主
- 保持选择器简洁
- 合理规划 CSS 架构
- 使用 BEM 命名法
调试技巧:
- 使用浏览器开发者工具
- 添加注释记录权重
- 使用调试样式