CSS 重新认识 !important 肯定有你不知道的

lxf2023-03-14 08:44:02
  • 重新认识 !important
    • 影响级联规则
      • 与 animation 和 transition 的关系
      • 级联层cascade layer
      • 内联样式
      • !important 与权重
    • !important 与简写属性
    • !important 与自定义变量
    • !important 最佳实践

在开始之前, 先来规范一下文中的用于, 首先看 W3C 中关于 CSS 的一些术语定义吧. 下图来自 W3C

CSS 重新认识 !important 肯定有你不知道的

我们将一个完整的 color: blue; 称为一个声明(declaration), 其中 color 称为属性(property), blue 称为值(value)

重新认识 !important

!important 表示 CSS 声明是「重要」的. !important 改变了 CSS 级联中究竟使用哪个 CSS 声明的规则. 如果一个 CSS 声明不是重要(important)的, 那么就称其为一般(normal)声明.

我们只需要将 !important 加在一个 CSS 声明的值的后面, 要加上至少一个空格, !important 之间可以有空格, 但是通常没有空格

.box {
  border-radius: 10px; /* normal declaration */
  font-size: 18px ! important; /* 可以, 但不推荐 */
  background-color: red !important; /* 可以, 推荐 */
}

影响级联规则

在级联规则中, 有三种常见的样式表, 他们的优先级依次 降低

  • author stylesheets: 最常见的样式表, 由 web 开发人员编写
  • user stylesheets: 大多数浏览器中, 网站的用户可以使用自定义的 user 样式表覆盖网站的样式. 根据浏览器的不同, user 样式表可以直接配置或者通过浏览器扩展添加.
  • user-agent stylesheets: 浏览器默认样式表.

一旦应用了 !important, 优先级就完全反过来. user-agent 所有 !important 样式表优先级大过 user 所有 !important 样式表优先级; 而 user 所有 !important 样式表优先级又大过 author 所有 !important 样式表优先级.

举个例子, 我们可以使用广告拦截器插件拦截页面某个元素. 本来 author 样式表的优先级高于 user 样式表, 但是因为 user 样式表中的 CSS 声明使用了 !important, 所以它的优先级就反过来高过 author 样式表中 !importantCSS 声明.

CSS 重新认识 !important 肯定有你不知道的

因此即便我们在 author 样式表中多加 display: block !important; 仍然无济于事, 元素 display 的计算属性还是 none. 这也就是使用广告拦截器插件拦截页面元素时, 网站开发者是没有能力覆盖插件的 user stylesheets 的原因.

CSS 重新认识 !important 肯定有你不知道的

反转 important 样式表优先级满足了用户的某些特殊要求, 比如要改变浏览器字体大小, 从而覆盖网页开发者编写的样式表. 同样的, user-agent 样式表中 important 声明的优先级更高也会阻止某些恶意插件破环页面功能等.

animationtransition 的关系

首先要注意的是, 在 @keyframes 中的声明不能使用 !important

CSS 重新认识 !important 肯定有你不知道的

所有 important 声明都比 animation 中声明的优先级高. 下面的例子中对 width 设置了 !important, 但是在动画中呢, 需要 width0100px 变化

.box2 {
  width: 100px !important;
  height: 100px;
  background-color: salmon;
  animation: moving linear 2s infinite;
}
@keyframes moving {
  from {
    width: 0;
    height: 0;
  }
  to {
    width: 200px;
    height: 100px;
  }
}

这条规则在 Chrome 109 版本Firefox 上的表现符合预期, 即元素的宽度始终为 100px 而不会动态变化, 但是在 Safari 15.6 上就不是啦. 至于为什么 Safari 浏览器表现不同于其他浏览器, 俺也不知道