目录
使用预处理器实现更DRY的代码
多于一个主题?没问题!
首页 web前端 css教程 在CSS中为主题着色的干方法

在CSS中为主题着色的干方法

Mar 26, 2025 am 09:55 AM

A DRY Approach to Color Themes in CSS

最近,Florens Verschelde 询问了如何在类和媒体查询中定义暗模式样式,同时避免重复声明CSS自定义属性。我过去也遇到过这个问题,但没有找到合适的解决方案。

我们的目标是避免在切换明暗模式时重新定义——从而重复——自定义属性。这是DRY(Don't Repeat Yourself)编程的目标,但切换主题的典型模式通常是这样的:

<code>:root {
  --background: #fff;
  --text-color: #0f1031;
  /* etc. */
}

@media (prefers-color-scheme: dark) {
  :root {
    --background: #0f1031;
    --text-color: #fff;
    /* etc. */
  }
}</code>
登录后复制

明白我的意思了吗?当然,在这个简短的例子中,它可能看起来并不重要,但想象一下一次处理几十个自定义属性——这是大量的重复!

然后我想起了Lea Verou 使用 --var: ; 的技巧,虽然一开始我没有想到,但我找到了一种方法让它工作:不是用 var(--light-value, var(--dark-value)) 或类似的嵌套组合,而是并排使用它们!

当然,肯定有人比我先发现这一点,但我还没有听说过利用(或者更确切地说,是滥用)CSS自定义属性来实现这一点。话不多说,这就是这个想法:

<code>--color: var(--light, orchid) var(--dark, rebeccapurple);</code>
登录后复制

如果 --light 值设置为 initial,则将使用回退值(orchid),这意味着 --dark 应设置为空格字符(这是一个有效值),使最终计算值如下所示:

<code>--color: orchid  ; /* 注意额外的空格 */</code>
登录后复制

相反,如果 --light 设置为空格,而 --dark 设置为 initial,我们最终得到一个计算值为:

<code>--color:   rebeccapurple; /* 同样,注意空格 */</code>
登录后复制

现在,这很好,但我们需要根据上下文定义 --light--dark 自定义属性。用户可以设置系统首选项(明或暗),也可以使用某些UI元素切换网站的主题。就像Florens的例子一样,我们将定义这三种情况,并使用Lea提出的“on”和“off”常量进行一些小的可读性增强,以便一目了然:

<code>:root { 
  /* 感谢Lea Verou!*/
  --ON: initial;
  --OFF: ;
}

/* 默认情况下,浅色主题处于启用状态 */
.theme-default,
.theme-light {
  --light: var(--ON);
  --dark: var(--OFF);
}

/* 默认情况下,暗色主题处于禁用状态 */
.theme-dark {
  --light: var(--OFF);
  --dark: var(--ON);
}

/* 如果用户偏好暗色,那么他们将获得暗色主题 */
@media (prefers-color-scheme: dark) {
  .theme-default {
    --light: var(--OFF);
    --dark: var(--ON);
  }
}</code>
登录后复制

然后,我们可以在一个声明中设置所有主题变量,而无需重复。在这个例子中,theme-* 类被设置为 html 元素,所以我们可以使用 :root 作为选择器,就像许多人喜欢做的那样,但如果自定义属性的级联特性更有意义,你也可以将它们设置为 body

<code>:root {
  --text: var(--light, black) var(--dark, white);
  --bg: var(--light, orchid) var(--dark, rebeccapurple);
}</code>
登录后复制

要使用它们,我们使用 var() 并内置回退,因为我们喜欢小心谨慎:

<code>body {
  color: var(--text, navy);
  background-color: var(--bg, lightgray);
}</code>
登录后复制

希望您已经开始看到这里的好处了。我们不是定义和切换大量的自定义属性,而是处理两个属性,并在 :root 上只设置其他所有属性一次。这与我们开始的地方相比有了巨大的改进。

使用预处理器实现更DRY的代码

如果让我脱离上下文来看下面这行代码,我肯定会感到困惑,因为颜色是一个单一的值,而不是两个!

<code>--text: var(--light, black) var(--dark, white);</code>
登录后复制

这就是为什么我更喜欢稍微抽象一下。我们可以使用我们最喜欢的预处理器(在我的例子中是Sass)来设置一个函数。如果我们保留上面定义的 --light--dark 值在不同上下文中的代码,我们只需要更改实际的自定义属性声明即可。让我们创建一个 light-dark 函数,它为我们返回CSS语法:

@function light-dark($light, $dark) {
  @return var(--light, #{ $light }) var(--dark, #{ $dark });
}
登录后复制

我们将像这样使用它:

:root {
   --text: #{ light-dark(black, white) };
   --bg: #{ light-dark(orchid, rebeccapurple) };
   --accent: #{ light-dark(#6d386b, #b399cc) };
}
登录后复制

你会注意到在函数调用周围有插值分隔符 #{ … }。如果没有这些,Sass 将按原样输出代码(就像普通的CSS函数一样)。您可以尝试各种实现方法,但语法复杂性取决于您的喜好。

这对于一个更DRY的代码库来说怎么样?

多于一个主题?没问题!

您可以使用两种以上的模式来实现这一点。您添加的主题越多,管理起来就越复杂,但关键是这是可能的!我们添加另一组ON或OFF变量的主题,并在值列表中设置一个额外的变量。

<code>.theme-pride {
  --light: var(--OFF);
  --dark: var(--OFF);
  --pride: var(--ON);
}

:root {
  --text:
    var(--light, black)
    var(--dark, white)
    var(--pride, #ff8c00)
  ; /* 换行符是完全有效的 */

  /* 其他要声明的变量… */
}</code>
登录后复制

这是个技巧吗?是的,绝对是。这是对潜在的、尚不存在的CSS布尔值的很好的用例吗?好吧,这是梦想。

你呢?你是否用不同的方法解决了这个问题?请在评论中分享!

以上是在CSS中为主题着色的干方法的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1653
14
CakePHP 教程
1413
52
Laravel 教程
1306
25
PHP教程
1251
29
C# 教程
1224
24
Google字体可变字体 Google字体可变字体 Apr 09, 2025 am 10:42 AM

我看到Google字体推出了新设计(Tweet)。与上一次大型重新设计相比,这感觉更加迭代。我几乎无法分辨出区别

如何使用HTML,CSS和JavaScript创建动画倒计时计时器 如何使用HTML,CSS和JavaScript创建动画倒计时计时器 Apr 11, 2025 am 11:29 AM

您是否曾经在项目上需要一个倒计时计时器?对于这样的东西,可以自然访问插件,但实际上更多

HTML数据属性指南 HTML数据属性指南 Apr 11, 2025 am 11:50 AM

您想了解的有关HTML,CSS和JavaScript中数据属性的所有信息。

如何通过CSS选择第一个类名为item的子元素? 如何通过CSS选择第一个类名为item的子元素? Apr 05, 2025 pm 11:24 PM

在元素个数不固定的情况下如何通过CSS选择第一个指定类名的子元素在处理HTML结构时,常常会遇到元素个数不�...

为什么Flex布局中的紫色斜线区域会被误认为是'溢出空间”? 为什么Flex布局中的紫色斜线区域会被误认为是'溢出空间”? Apr 05, 2025 pm 05:51 PM

关于Flex布局中紫色斜线区域的疑问在使用Flex布局时,你可能会遇到一些令人困惑的现象,比如在开发者工具(d...

使Sass更快的概念证明 使Sass更快的概念证明 Apr 16, 2025 am 10:38 AM

在一个新项目开始时,Sass汇编发生在眼睛的眨眼中。感觉很棒,尤其是当它与browsersync配对时,它重新加载

在前端开发中,如何使用CSS和JavaScript实现类似Windows 10设置界面的探照灯效果? 在前端开发中,如何使用CSS和JavaScript实现类似Windows 10设置界面的探照灯效果? Apr 05, 2025 pm 10:21 PM

在前端开发中如何实现类似Windows...

我们如何创建一个在SVG中生成格子呢模式的静态站点 我们如何创建一个在SVG中生成格子呢模式的静态站点 Apr 09, 2025 am 11:29 AM

格子呢是一块图案布,通常与苏格兰有关,尤其是他们时尚的苏格兰语。在Tar​​tanify.com上,我们收集了5,000多个格子呢

See all articles