如何重置 CSS 变量(又名自定义属性)并使用后备变量?

how to reset a CSS variable (aka custom properties) and use the fallback one?

我正在尝试为盒子模型属性设置 CSS 个变量。我想支持为各方和个别方面设定价值。我想有默认值,但无论哪种方式都可以覆盖。 我尝试使用回退值,但收效甚微。

类似于:

:root {
  --border-width-top: 0;
  --border-width-right: 0;
  --border-width-bottom: 0;
  --border-width-left: 0;
  --border-width: 0;
}
div {
  border-color: red;
  border-style: solid;
  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));
}


div {
  --border-width-top: 10px;
}

这将不起作用,因为如果 border-width 具有默认值,那么它将始终优先于后备值。 不确定目前有没有办法做到这一点,但我觉得很接近找到解决方案。

这是我正在玩的 stackblitz:stackblitz

fallback 值仅在未定义变量 --border-width 时有效:

The custom property's fallback value, which is used in case the custom property is invalid in the used context.

MDN

参见下面的演示:

:root {
  --border-width-top: 0;
  --border-width-right: 0;
  --border-width-bottom: 0;
  --border-width-left: 0;
  /*--border-width: 0;*/
}

div {
  border-color: red;
  border-style: solid;
  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));
}

div {
  --border-width-top: 10px;
}
<div id="app">
  <h1>TypeScript Starter</h1>
</div>

您可以使用 initial 取消设置值以使用备用值:

:root {
  --border-width-top: 2px;
  --border-width-right: 2px;
  --border-width-bottom: 2px;
  --border-width-left: 2px;
  --border-width: 0;
}
div {
  margin:5px;
  border-color: red;
  border-style: solid;
  border-width: var(--border-width, var(--border-width-top) var(--border-width-right) var(--border-width-bottom) var(--border-width-left));
}


div.box {
  --border-width:initial;
  --border-width-top: 10px;
}
<div>some content</div>
<div class="box">some content</div>

来自 the specification:

The initial value of a custom property is an empty value; that is, nothing at all. This initial value has a special interaction with the var() notation, which is explained in the section defining var().

To substitute a var() in a property’s value:

  1. If the custom property named by the first argument to the var() function is animation-tainted, and the var() function is being used in the animation property or one of its longhands, treat the custom property as having its initial value for the rest of this algorithm.
  2. If the value of the custom property named by the first argument to the var() function is anything but the initial value, replace the var() function by the value of the corresponding custom property. Otherwise,
  3. if the var() function has a fallback value as its second argument, replace the var() function by the fallback value. If there are any var() references in the fallback, substitute them as well.
  4. Otherwise, the property containing the var() function is invalid at computed-value time

正如@Temani 所解释的那样,您可以使用 --varName: initial 为变量设置有效的空但无效值。那么var(....)中的any fallback values declared就会被使用。

因此,如果您定义 --text_color: initial,则使用选择器:color: var(--text_color, hotpink) 您的文字将是粉红色而不是黑色(如果您直接写 color: initial 就会是黑色)。


然后我想知道是否可以使用 unset 而不是 initial。使用 --text_color: unset 取消定义变量似乎更自然。它更直观,因为您可能很少使用 unset,您会记住您的意图。

然而 结果表明 unsetinitial 的工作方式并不完全相同,但如果您需要继承声明为更高级别的变量,偶尔可能会有用向上。

--text_color: initial

  • 将变量的值设置为空值(参见 Tamani 的回答中引用的规范)
  • 任何设置 --text_color 的祖先节点都将被此声明覆盖
  • 我喜欢这样想,就好像你可以设置 --text_color: null

--text_color: unset

  • 有效地从 DOM 节点中完全删除变量。它没有将它设置为神奇的 空值 - 它的行为方式与您刚刚从代码中完全删除它的方式相同。
  • 这允许使用任何继承的值。
  • 我喜欢这样想,就好像你可以设置 --text_color: undefined
  • 因此,如果任何祖先 DOM 节点定义 --text_color: green 并且您的节点声明 --text_color: unset 以及 color: var(--text_color, blue),它将是绿色而不是蓝色。

这对我很有用,因为我动态设置了很多变量,需要取消设置,就像从未设置过一样。

我不能保证这是否是实际的规范行为:-)

您也可以在 Javascript 中执行此操作:

element.style.setProperty('--button_icon_active_color', '')
element.style.setProperty('--button_icon_active_color', null)

这两个 'unset' 值就好像它从未存在过一样。

如果您 运行 在浏览器控制台中执行此命令,您会看到它从样式中消失。