【问题标题】:CSS variables defaults: set if not already setCSS 变量默认值:如果尚未设置,则设置
【发布时间】:2020-03-19 18:03:40
【问题描述】:

我的 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>

【问题讨论】:

  • 我的理论是 --my-variable 是不是在内联样式范围内

标签: css css-variables


【解决方案1】:

: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>

【讨论】:

    【解决方案2】:

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

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

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


    来自the specification

    自定义属性几乎完全不计算,除了它们允许并计算 var() 函数的值。 这可以创建循环依赖关系,其中自定义属性使用 var() 引用自身,或者两个或多个自定义属性都尝试相互引用。

    为每个元素创建一个有向依赖图,其中包含每个自定义属性的节点。如果自定义属性 prop 的值包含引用属性 var 的 var() 函数(包括在 var() 的后备参数中),则在 prop 和 var 之间添加一条边。边缘可能从自定义属性到自身。 如果依赖图中存在循环循环中的所有自定义属性都必须计算到它们的初始值(这是一个保证无效的值)。

    【讨论】:

    • 优秀的答案。我的问题缺少一个细节:CSS 在 Shadow DOM 中。我无法访问上层。您对这种情况有什么建议吗?
    • @mikabytes 你可以考虑:host 元素,在你的情况下它应该是上层
    • 那会破坏继承,对吧?但同意只要消费者直接针对我的组件就足够了。
    • @mikabytes 它可能会影响继承,但仅限于您的组件内部,因此这取决于您的组件的构建方式以及您在内部使用 CSS 变量的方式。
    • 只有直接在我的组件上设置的变量才会进入我的组件,如此处所示gist.github.com/mikabytes/83779917befa6e97f541a93305aa46f3 不幸的是,这意味着没有好的方法可以在不破坏继承的情况下设置 Web 组件变量默认值。
    【解决方案3】:

    为了补充前面的答案,可能存在您不想在全局 :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 或其他一些后缀。

    【讨论】:

    • 这是相关的。因为这允许--my-variable-inner 的默认值,并具有全局支持。我只是希望无需引入新变量就可以做到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-01
    相关资源
    最近更新 更多