!important 的作用
在值的后面加上 !important,这条声明就会胜过同一元素上同一属性的所有普通声明。选择器的优先级和源码顺序都不再起作用。
没有 !important 的话,ID 选择器会胜出,文字会是蓝色。在编辑器里删掉 !important 就能看到。
语法
selector {
property: value !important;
}
它写在值的后面、分号的前面。它只作用于这一条声明,而不是整条规则。它也可以用在简写属性中(margin: 0 !important; 让四个方向都变成 important),以及 style 属性中。
谁胜过谁
对于页面作者编写的样式,从弱到强依次是:
| 等级 | 声明 | 示例 |
|---|---|---|
| 1 | 样式表中的普通声明 | p { color: blue; } |
| 2 | style 属性中的普通声明 | <p style="color: blue"> |
| 3 | 样式表中的 !important | p { color: blue !important; } |
| 4 | style 属性中的 !important | <p style="color: blue !important"> |
在同一个等级内,先比优先级,再比声明出现的顺序:后出现的胜出。
这是 !important 在日常中唯一正当的用法:覆盖一个你无法修改的内联样式,比如第三方小组件写入的样式。
两条声明都是 !important 时
!important 对上 !important,就回到常规规则:优先级高的胜出,优先级相同时后写的声明胜出。
!important 就是这样不断升级的:一旦某条规则用了它,要覆盖这条规则的规则也必须用它,优先级又开始一路攀升。
一张表看懂 CSS 优先级
优先级就是选择器的权重。数三个数字:
| 列 | 计入的内容 | 示例选择器 | 优先级 |
|---|---|---|---|
| A | ID 选择器 | #nav | (1,0,0) |
| B | 类、属性、伪类 | .btn、[type="text"]、:hover | 每个 (0,1,0) |
| C | 类型选择器、伪元素 | p、::before | 每个 (0,0,1) |
| 无 | *、组合符(>、+、~、空格) | *、ul > li | 不增加权重 |
先比较 A 列;只有相同时才看 B 列,然后是 C 列。所以 #nav a(1,0,1)胜过 .menu .item .link a(0,3,1):一个 ID 的分量超过任意数量的类。
理解了这张表,你就能避免使用 !important:大多数“我的 CSS 不生效”的问题,都是因为别处有一条优先级更高的规则,在开发者工具的 Styles 面板里可以看到你的声明被划掉了。
更干净的替代方案
- 让优先级持平,再依靠顺序。 在库的样式表之后加载你自己的样式表,并使用一个至少同样具体的选择器。
- 用
:where()降低另一条规则的优先级。:where()里面的一切都算作零,所以用它编写的基础样式很容易被覆盖。 - 用 CSS 变量作为入口。 一个读取
var(--btn-bg)的组件不必和它的选择器较劲就能换主题。参见 CSS 变量。
用 JavaScript 设置 !important
element.style.color = 'red !important' 是行不通的:这个值无效,会被忽略。请使用带第三个参数的 setProperty:
el.style.setProperty('color', '#f59e0b', 'important');
常见错误
- 写错了位置。
color: !important red;是无效的;它要写在值的后面。 - 在
@keyframes里使用。 关键帧里标记了!important的声明会被忽略。 - 每个冲突都用它来解决。 应该在开发者工具里找到胜出的那条规则,让你的优先级与它持平,或者降低它的优先级。
- 以为它会影响另一个属性。
color: red !important对background毫无作用。 - 忘了内联的
!important会胜过你的。 页面样式表中没有任何规则能覆盖style="color: red !important";只能修改这个属性本身,比如用 JavaScript。
常见问题
CSS 中的 !important 有什么作用?
它让一条声明优先于同一元素上同一属性的所有普通声明,不管选择器的优先级或书写顺序如何。把它写在值的后面:color: red !important;。
怎么覆盖 !important?
用另一条 !important 声明,它的优先级更高,或者优先级相同但在样式表中位置更靠后。带 !important 的内联 style 胜过样式表中所有的 !important。
!important 能覆盖内联样式吗?
能。样式表中带 !important 的声明胜过 style 属性中的普通声明。但它无法胜过本身也标记了 !important 的内联声明。
使用 !important 是不好的做法吗?
如果用它来打赢优先级之争,是的:下一次覆盖也得用 !important,样式表就会变得难以修改。对于必须始终生效的工具类(比如 .hidden)、覆盖第三方的内联样式,以及用户样式表,使用它是合理的。
CSS 优先级是怎么计算的?
数三列:ID 选择器;类、属性和伪类;类型选择器和伪元素。从第一列开始逐列比较,所以 #nav a(1,0,1)胜过 .menu .item a(0,2,1)。通用选择器 * 和组合符不增加任何权重。