zjffun blog

CSS 变量优先级“错误”

更新于 写于 CSS

首先我们来看一个简单的问题,下面的代码 .div2 的背景色应该是红色,浅蓝色还是浅绿色?

html
<style>
  :root {
    --color: red;
  }
  .div1 {
    --color: lightblue;
    --bg-color: var(--color);
  }
  .div2 {
    --color: lightgreen;
    background: var(--bg-color);
  }
</style>
<div class="div1">
  <div class="div2">test</div>
</div>

我们都知道 CSS 的第一个字母 C 代表 Cascading(中文是层叠),表示样式可以有多个来源,发生冲突时取优先级最高的样式作为最终样式。所以我们可以猜测 .div2 的背景色应该是浅绿色,因为 .div2background 属性的值是 var(--bg-color),而 --bg-color 的值是 var(--color),而 --color 的值按优先级最高的应该是 lightgreen,所以 .div2 的背景色应该是浅绿色。

我们可以先看一下开发者工具给出的结果:

devtool

点击之后是跳到了 lightgreen ,奇怪的是前面的方框和鼠标悬浮展示的颜色是 lightblue

看一下最终渲染出来的结果:

test

居然是浅蓝色,是浏览器 bug 导致优先级“错误”了么?

我们再来看一个CSS 规范中的例子

html
<one>
  <two>
    <three />
  </two>
</one>
<style>
  one {
    --foo: 10px;
  }
  two {
    --bar: calc(var(--foo) + 10px);
  }
  three {
    --foo: calc(var(--bar) + 10px);
  }
</style>

three--foo 应该是是多高?答案是 30px

It is important to note that custom properties resolve any var() functions in their values at computed-value time, which occurs before the value is inherited. In general, cyclic dependencies occur only when multiple custom properties on the same element refer to each other; custom properties defined on elements higher in the element tree can never cause a cyclic reference with properties defined on elements lower in the element tree.

翻译:

需要注意的是,自定义属性会在计算值时(继承之前)在其值中解析 var() 函数。一般来说,只有当同一个元素上的多个自定义属性相互引用时,才会发生循环依赖;在元素树中较高位置的元素上定义的自定义属性,永远不会导致元素树中较低位置元素上定义的属性的循环引用。

现在我们可以得到一个简单的答案,这不是浏览器的 bug(虽然开发者工具有一些 bug),而是有意这样设计的,为了避免循环引用。

练习:

更多练习: