CSS 变量默认值:如果尚未设置则设置

CSS variables defaults: set if not already set

我的 Web 组件使用 CSS 个变量。

这些变量需要默认值。

它们在许多文件中使用,所以我想提供默认值一次,而且只提供一次

第一次尝试使文本变黑。为什么?

一次提供默认值的正确方法是什么?

.a {
  --my-variable: red;
}

.b {
  --my-variable: var(--my-variable, blue);
}
<div class="a">
  <div class="b">
    <span style="color: var(--my-variable);">text</span>
  </div>
</div>

:root 中声明默认值,然后在选择器中覆盖。

:root {
  --primary-color: red;
}

* {
  color: var(--primary-color);
  border: 1px solid var(--primary-color);
  padding: 0.25rem;
  margin: 0;
}

div {
  --primary-color: green;
}

p {
  --primary-color: blue;
}
<div>HI!</div>
&hellip;
<p>Bye!</p>

This first attempt makes the text black. Why?

因为这个 --my-variable: var(--my-variable, blue); 是无效的,因为你试图用它自己来表达同一个变量,这是不允许的,所以浏览器会简单地忽略它。然后稍后当使用 color: var(--my-variable); 时,颜色将回退到 initial 值,即黑色。

正确的方法是简单地在上层定义变量,它会被所有元素继承(就像@kornieff提供的解决方案)


来自the specification

Custom properties are left almost entirely unevaluated, except that they allow and evaluate the var() function in their value. This can create cyclic dependencies where a custom property uses a var() referring to itself, or two or more custom properties each attempt to refer to each other.

For each element, create a directed dependency graph, containing nodes for each custom property. If the value of a custom property prop contains a var() function referring to the property var (including in the fallback argument of var()), add an edge between prop and the var. Edges are possible from a custom property to itself. If there is a cycle in the dependency graph, all the custom properties in the cycle must compute to their initial value (which is a guaranteed-invalid value).

为了补充前面的答案,在某些情况下您可能不想在全局 :root 范围内声明变量。例如,当您创建一个可重用组件时,您希望在本地声明其样式,而不依赖于全局项目样式。特别是如果您正在为其他开发人员构建库。

在这种情况下,解决方案是将一个变量名暴露给“外部世界”,并在组件内部使用不同的变量名。组件容器应该只是将可选的外部变量映射到内部变量,并设置其默认值:

.my-component-container {
  /* map optional "external" variables to required "internal" variables */
  --my-variable-inner: var(--my-variable, blue);
}

.my-component-container .my-nested-element {
  color: var(--my-variable-inner);
}

.my-component-container .my-other-nested-element {
  border-color: var(--my-variable-inner);
}

这样你可以确保 --my-variable-inner 总是在组件中定义,并使外部消费者可以选择定义 --my-variable.

缺点是你需要记住两个变量名而不是一个。但是在这里你可以想到一些项目范围的约定,例如像那样向每个变量添加 --inner 或其他一些后缀。