从内部范围覆盖 :root CSS 变量 [英] Overriding :root CSS variables from inner scopes

查看:116
本文介绍了从内部范围覆盖 :root CSS 变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 Stack Overflow 的设计系统中,我们使用 Less 来编译 CSS 颜色值.

我们有全局 Less 变量,例如 @orange-500,它们经常针对悬停状态、构建边框样式、背景颜色等进行修改.

在 Less 中,这被写成 darken(@orange-500, 5%).我正在尝试使用本机 CSS 变量实现类似的功能.切换到 CSS 变量将使我们能够更快地发布依赖主题(堆栈交换网络、暗模式等)的功能,使用更少的 CSS 行,同时在媒体查询上启用交换变量(高对比度、暗模式等).

这个在 hsl 中覆盖颜色亮度值的示例在变量范围限定为 CSS 类时起作用:

.card {--orange: hsl(255, 72%, var(--lightness, 68%));背景:var(--orange);}.card:悬停{--亮度:45%;}

你好,世界

然而,我们需要在一个单一的、可交换的地方全局指定我们的颜色变量以支持全局主题,但这并不能按预期工作:

:root {--orange: hsl(255, 72%, var(--lightness, 68%));}.卡片 {背景:var(--orange);}.card:悬停{--亮度:45%;}

你好,世界

我尝试从 :root 切换到 htmlbody ,但没有任何运气.对此有什么解决方法吗?

解决方案

这是一个范围界定问题.你这样做的方式,你是从 :root--orange 继承 --orange:root 的亮度为 68%.

为了更改它,您需要将 --orange 变量的范围重新设置为将查找新的 --lightness 值的元素.有几种方法可以解决这个问题:

选项 1:复制元素上的 --orange 变量:

:root {--亮度:68%;--orange: hsl(255, 72%, var(--lightness));}.卡片 {背景:var(--orange);--orange: hsl(255, 72%, var(--lightness));}.card:悬停{--亮度:45%;}

你好,世界

显然这有点糟糕,因为您将不得不复制那个 --orange 变量.

选项 2:您可以抽象 --orange 的其他参数,以免重复.尽管文本更多,但我还是会喜欢这种方法:

:root {--亮度:68%;--orangeHue: 255;--orangeSat:72%;--orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));}.卡片 {背景:var(--orange);--orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));}.card:悬停{--亮度:45%;}

你好,世界

您可以做的是将其范围专门用于可能应用于 HTML 元素或正文的 .darkMode 类.这也很有意义,因为从代码中可以清楚地看出意图是什么:

选项 3

:root {--亮度:68%;--orangeHue: 255;--orangeSat:72%;--orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));}.卡片 {背景:var(--orange);}.card:悬停{--亮度:45%;}.darkMode .card {--orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));}

 

<div class="card">你好,世界

不管你怎么走,问题是 --orange 变量是从其设置 --lightness 的原始范围继承的.将其视为继承计算值".

为了让 --orange 获得新的亮度,你需要一个新的 --orange 某处.

选项 4

我不确定您的主题模式是什么,但我可以解释我如何在自己的博客上创建暗模式 .如果你看看 CSS 什么你会看到我创建了两个遵循相同命名约定的完整主题:

--themeLightTextColor: rgb(55, 55, 55);--themeLightBGColor: rgb(255, 255, 255);--themeLightAccentColor: rgb(248, 248, 248);--themeLightTrimColor: rgb(238, 238, 238);--themeDarkTextColor: rgb(220, 220, 220);--themeDarkBGColor: rgb(23, 23, 23);--themeDarkAccentColor: rgb(55, 55, 55);--themeDarkTrimColor: rgb(40, 40, 40);

然后我要做的是创建一个第三组变量,它们的工作是成为主动"经理:

--themeActiveLinkColor: var(--linkColor);--themeActiveLinkColorHover: var(--linkColorHover);--themeActiveTextColor: var(--themeLightTextColor);--themeActiveEditorialTextColor: var(--themeLightPltNlow);--themeActiveBGColor: var(--themeLightBGColor);--themeActiveAccentColor: var(--themeLightAccentColor);--themeActiveTrimColor: var(--themeLightTrimColor);

然后,我将活动主题设置范围限定在一个类下:

.theme--dark {--themeActiveTextColor: var(--themeDarkTextColor);--themeActiveEditorialTextColor: var(--themeDarkPltNlow);--themeActiveBGColor: var(--themeDarkBGColor);--themeActiveAccentColor: var(--themeDarkAccentColor);--themeActiveTrimColor: var(--themeDarkTrimColor);}

似乎您的意图是不必显式声明主题,而是调整一些根变量"来调整它.但我建议您可能有一个模式,单个类可以更改活动主题.这种模式的优点是您还可以调整类名上的任何根变量".

In our design system at Stack Overflow, we use Less to compile CSS color values.

We have global Less variables like @orange-500 that are frequently modified for hover states, building border styling, background colors, etc.

In Less, this is written as darken(@orange-500, 5%). I'm trying to achieve something similar using native CSS variables. Switching to CSS variables will allow us to ship features that rely on theming (Stack Exchange Network, Dark Mode, etc.) much faster, with way fewer lines of CSS, while enabling swapping variables on media query (high contrast, dark mode, etc).

This example of overriding our color’s lightness value in hsl works when the variables are scoped to a CSS class:

.card {
  --orange: hsl(255, 72%, var(--lightness, 68%));
  background: var(--orange);
}
.card:hover {
  --lightness: 45%;
}

<div class="card">
  Hello world
</div>

However, we need to specify our color variables globally in a single, swappable place to support global theming, but this doesn't work as expected:

:root {
  --orange: hsl(255, 72%, var(--lightness, 68%));
}
.card {
  background: var(--orange);
}
.card:hover {
  --lightness: 45%;
}

<div class="card">
  Hello world
</div>

I've tried switching from :root to html or body without any luck. Any workarounds to this?

解决方案

This is a scoping issue. The way you're doing it, you're inheriting --orange from the :root, and --orange in the :root has a lightness of 68%.

In order to change it, you'll want to re-scope the --orange variable to an element that will look up the new --lightness value. There's a few ways to pull this off:

Option 1: duplicate the --orange variable on the element:

:root {
  --lightness: 68%;
  --orange: hsl(255, 72%, var(--lightness));
}
.card {
  background: var(--orange);
  --orange: hsl(255, 72%, var(--lightness));
}
.card:hover {

  --lightness: 45%;
}

<div class="card">
  Hello world
</div>

Obviously this kinda stinks, because you're going to have to duplicate that --orange variable.

Option 2: You could abstract the other parameters of --orange so that it's not as duplicative. I'd be a fan of this approach despite the fact that it's more text:

:root {
  --lightness: 68%;
  --orangeHue: 255;
  --orangeSat: 72%;
  --orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));
}
.card {
  background: var(--orange);
  --orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));
}
.card:hover {

  --lightness: 45%;
}

<div class="card">
  Hello world
</div>

What you could also do is scope this specifically to a .darkMode class that might be applied to the HTML element or the body. This could also make sense because it's clear what the intent is from the code:

Option 3

:root {
  --lightness: 68%;
  --orangeHue: 255;
  --orangeSat: 72%;
  --orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));
}

.card {
  background: var(--orange);

}
.card:hover {
  --lightness: 45%;
}
.darkMode .card {
  --orange: hsl(var(--orangeHue), var(--orangeSat), var(--lightness));
}

  <div class="darkMode">
    <div class="card">
      Hello world
    </div>
  </div>

Regardless of how you go, the issue is that the --orange variable is inheriting from its original scope where --lightness is set. Think of it as "inheriting a computed value".

In order to get --orange to get the new lightness, you need a new --orange somewhere.

Option 4

I'm not sure what your theme pattern is, but I can explain how I created a dark mode on my own blog . If you look at the CSS What you'll see is that I've created two complete themes that follow the same naming convention:

--themeLightTextColor: rgb(55, 55, 55);
--themeLightBGColor: rgb(255, 255, 255);
--themeLightAccentColor: rgb(248, 248, 248);
--themeLightTrimColor: rgb(238, 238, 238);
--themeDarkTextColor: rgb(220, 220, 220);
--themeDarkBGColor: rgb(23, 23, 23);
--themeDarkAccentColor: rgb(55, 55, 55);
--themeDarkTrimColor: rgb(40, 40, 40);

What I then do is create a third set of variables whose job it is to be the "active" managers:

--themeActiveLinkColor: var(--linkColor);
--themeActiveLinkColorHover: var(--linkColorHover);
--themeActiveTextColor: var(--themeLightTextColor);
--themeActiveEditorialTextColor: var(--themeLightPltNLow);
--themeActiveBGColor: var(--themeLightBGColor);
--themeActiveAccentColor: var(--themeLightAccentColor);
--themeActiveTrimColor: var(--themeLightTrimColor);

Then, I scope the active theme settings under a single class:

.theme--dark {
   --themeActiveTextColor: var(--themeDarkTextColor);
   --themeActiveEditorialTextColor: var(--themeDarkPltNLow);
   --themeActiveBGColor: var(--themeDarkBGColor);
   --themeActiveAccentColor: var(--themeDarkAccentColor);
   --themeActiveTrimColor: var(--themeDarkTrimColor);
}

It seems like maybe your intent is to not have to explicitly declare a theme, but rather tweak some "root variables" to adjust it. But I would suggest that maybe you have a pattern in place where a single class can change an active theme. The advantage to this pattern is that you would be able to also adjust any "root variables" on the class name.

这篇关于从内部范围覆盖 :root CSS 变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆