如何使用 CSS 变量在网站上实现暗黑模式

最后更新: 28/01/2026
作者: 艾萨克
  • 在 :root 中使用 CSS 变量可以定义一个通用调色板,并且只需修改这些值即可在浅色模式和深色模式之间切换。
  • 结合 html/body 中的 prefers-color-scheme、类或属性以及 JavaScript 开关,可以实现自动和手动控制。
  • 将用户选择的主题存储在 localStorage 中,可以确保网站在用户下次访问时记住该主题。
  • 注重对比度、强调色和易用性,可以使…… 黑暗模式 这带来的是体验的真正提升,而不仅仅是视觉效果。

CSS

如果你从事前端开发一段时间了,很可能已经接触过网页界面中流行的暗黑模式。这并非一时风潮:人们喜欢它,它在夜间对眼睛更友好,看起来更现代,而且如果做得好,甚至还能提升网站的易用性。好消息是,你无需搞得一团糟:只需CSS 变量、媒体查询和少量可选的 JavaScript,就能拥有一个非常强大的主题系统。

接下来您将看到不同的方法 使用 CSS 变量在网站上实现暗黑模式:来自无 JavaScript 解决方案和 技巧:has()……直至完成配置并持久化 localStorage 和支持 prefers-color-scheme这样做的目的是让你充分理解各个部分,以便你能够根据自己的喜好将它们组合起来,而不仅仅是复制粘贴。

为什么值得提供深色模式

除了美观之外,深色模式还具有几个显而易见的优势。首先,它可以减少弱光环境下的眩光,帮助许多人更舒适地长时间阅读。其次,在 OLED 和类似屏幕上,黑色像素会被关闭,从而节省电量——您的移动用户一定会喜欢这一点。

还有一个组件 可访问性和定制: 许多 操作系统 它们已经允许用户全局选择浅色或深色主题,甚至可以通过 CSS 来表达这种偏好。 prefers-color-scheme如果你的网站尊重用户的选择,你就能提供更一致的体验,照顾到对光线敏感的人,并在可用性方面得分。

基础知识:CSS变量作为主题的基础

防止这一切演变成样式重复噩梦的关键在于: 自定义 CSS 属性也就是说,著名的CSS变量。它们充当值的容器,然后你可以在整个文档中重复使用这些值。 var()如果把这些变量组织得当,改变主题就如同重新赋几个值一样简单。

通常的做法是在代码块中定义全局变量集。 :root指向该元素 <html>。从那里, 整个文档都将采用这些颜色。一个主题清晰的简化示例可以是:

:root {
  --color-fondo: #ffffff;
  --color-texto: #222222;
  --color-acento: #007bff;
}

body {
  background: var(--color-fondo);
  color: var(--color-texto);
}

a, button {
  color: var(--color-acento);
}

当你想要一个深色主题时,与其重写所有的选择器, 只有在特定条件下才会重新定义这些变量。 (一个类、一个属性、一个媒体查询、一个选择器) :has()……)。因此,对于所有可能因主题而异的内容(例如背景、文本、边框、阴影,甚至字体或图像),习惯使用变量非常重要。

仅使用 CSS 的 `:has()` 属性和复选框实现深色模式

有一种非常巧妙的方法,无需编写 JavaScript 代码即可激活深色主题,那就是利用关系选择器。 :has()这个想法是将它与……结合起来 用作开关的复选框 当选中该复选框时,重新定义变量。对于单视图页面、演示或小型实验而言,这是一个理想的解决方案,因为它不提供跨页面持久性。

流程如下:首先,您需要在……中定义默认颜色。 :root然后你制作 body 使用这些变量,然后使用 body:has(#darkmode-toggle:checked)选中复选框时更改值。CSS 代码可能如下所示:

/* Colores por defecto (modo claro) */
:root {
  --bg-color: #ffffff;
  --text-color: #222222;
}

body {
  background: var(--bg-color);
  color: var(--text-color);
  transition: background 0.3s, color 0.3s;
}

/* Cuando el checkbox esté marcado, usamos los colores oscuros */
body:has(#darkmode-toggle:checked) {
  --bg-color: #1e1e1e;
  --text-color: #f5f5f5;
}

在 HTML 代码中,你只需要将复选框放置在某个位置即可。 <body> 并用相同的方式引用它 你在选择器中使用的 id:

<input type="checkbox" id="darkmode-toggle">
<label for="darkmode-toggle">Modo oscuro</label>

这种方法的好处是 你不受任何特定结构的束缚。复选框可以放在页眉、侧边栏或任何你想要的位置,只要它在……范围内即可。 body问题在于,由于没有 JavaScript 或 存储一旦刷新页面或更改 URL,主题就会丢失,页面会恢复到初始状态。对于多页面网站来说,这种方法不够完善,但作为一种纯 CSS 技巧,它非常简洁。

  如何掌握 Adob​​e Lightroom 预设和调整功能来改变你的照片

利用首选配色方案来遵循系统

现代深色模式的另一个重要方面是让设备本身 浏览器和操作系统表明偏好 来自用户。这就是媒体查询的作用。 prefers-color-scheme这样,您可以根据用户设备上设置的是浅色主题还是深色主题来应用不同的样式。

使用此媒体查询有两种非常常见的方法。一种方法是定义两个独立的块,一个用于浅色,一个用于深色,并在每种情况下重新赋值变量:

/* Valores por defecto para el modo claro */
:root {
  --body-bg: #ffffff;
  --body-color: #000000;
}

/* Si el usuario prefiere modo oscuro */
@media (prefers-color-scheme: dark) {
  :root {
    --body-bg: #000000;
    --body-color: #ffffff;
  }
}

另一种替代方案是反过来:仅在媒体查询中定义深色模式,并让其余值默认用作“浅色模式”,即使对于规范中可能添加的未来值也是如此:

/* Tema claro por defecto */
:root {
  --body-bg: #ffffff;
  --body-color: #000000;
}

/* Tema oscuro si el sistema lo indica */
@media (prefers-color-scheme: dark) {
  :root {
    --body-bg: #000000;
    --body-color: #ffffff;
  }
}

然后,您只需在样式表中使用这些变量,例如在文档主体中:

body {
  background: var(--body-bg);
  color: var(--body-color);
}

这样一来,您的网站就能自动适应系统设置。如果有人在移动设备或桌面电脑上切换到深色模式,浏览器会自动调整您的设置;请注意不同浏览器(例如三星浏览器和 Chrome)之间的差异。但是,目前仍然没有手动切换或针对特定网站的持久化设置:您只是在“服从”系统。

使用 HTML、CSS 和 JavaScript 创建主题切换功能

如果你想更进一步,赋予用户控制权,通常的做法是添加一个 按钮或开关 这样就可以手动切换浅色和深色主题。HTML 代码可以很简单,比如在标签内添加一个复选框。 label或者,也可以是一对带有太阳和月亮图标的按钮。

例如,一种非常常见的做法是使用看起来像开关的复选框:

<header>
  <div class="switch-wrapper" id="switch">
    <label>
      <input type="checkbox">
      <span class="slider"></span>
    </label>
  </div>
  <h1>Mi sitio con modo oscuro</h1>
</header>

滑块通过 CSS 设置样式,使其看起来像一个开/关按钮,但重要的是…… input在 CSS 中,你需要为主题定义变量并将它们应用到元素上,然后使用 JavaScript 来…… 更改根元素的类或属性 当复选框状态改变时。

例如,在以下情况下使用自定义属性: htmltema:

/* Tema claro por defecto */
:root {
  --color-fondo: #ffffff;
  --color-texto: #222222;
}

/* Tema oscuro */
:root {
  --color-fondo: #121212;
  --color-texto: #e0e0e0;
}

body {
  background-color: var(--color-fondo);
  color: var(--color-texto);
}

响应开关变化的 JavaScript 代码可能是这样的:

const colorSwitch = document.querySelector('#switch input');

function cambiaTema(ev) {
  if (ev.target.checked) {
    document.documentElement.setAttribute('tema', 'dark');
  } else {
    document.documentElement.setAttribute('tema', 'light');
  }
}

colorSwitch.addEventListener('change', cambiaTema);

用户点击后,根元素的属性会立即更新,借助 CSS 变量,整个网站的外观就会随之改变,而无需您修改任何其他样式。这种方法非常灵活:您只需添加新的值和选择器,即可轻松添加更多主题(例如霓虹色、棕褐色、高对比度等)。

通过类、更多主题和最少的 JavaScript 进行切换

另一种非常类似的方法是使用类而不是属性,如果您已经使用过工具类或框架,这种方法会更熟悉。例如,您可以在 CSS 中定义以下内容:

:root.light {
  --bg-color: #ffffff;
  --text-color: #222222;
}

:root.dark {
  --bg-color: #121212;
  --text-color: #e0e0e0;
}

body {
  background: var(--bg-color);
  color: var(--text-color);
}

之后,只需一行 JavaScript 代码,即可通过为根元素分配相应的类来控制主题。一个典型的函数如下:

function setTheme(theme) {
  document.documentElement.className = theme;
}

然后您只需从控件中调用该函数即可。例如,对于两个按钮:

<button onclick="setTheme('light')" title="Usar tema claro">☀️</button>
<button onclick="setTheme('dark')" title="Usar tema oscuro">🌙</button>

如果要添加更多配色方案,只需在代码中声明新的类即可。 :root (例如: .neon, .sepia等等)重新定义变量集,并将这些值传递给 setTheme由于 整个布局使用 var()其他任何内容都不需要更改。

  8 个最佳 PC 网络电视节目

多主题选择器和本地存储

当您想要更井然有序的布局时,尤其是在提供多个调色板的情况下,一个元素就显得尤为重要。 <select> 它非常合适。其理念是每个选项都有…… 值是类的名称 或者主题标识符,而 JavaScript 只是将该类应用于 <html><body>.

一个初始的 HTML 代码可能是:

<label for="theme-select">Tema de color:</label>
<select id="theme-select">
  <option value="theme-auto">Automático</option>
  <option value="theme-light">Claro</option>
  <option value="theme-dark">Oscuro</option>
</select>

在 CSS 中,您可以定义基本配置(例如,浅色模式),然后在此基础上创建变体作为类。 body ØEL html:

body {
  --bg-color: #ffffff;
  --text-color: #222222;
  background: var(--bg-color);
  color: var(--text-color);
}

body.theme-dark {
  --bg-color: #121212;
  --text-color: #e0e0e0;
}

body.theme-auto {
  /* valores por defecto; se ajustarán con media queries */
}

对于自动选项,您可以将其与 prefers-color-scheme 从而:

@media (prefers-color-scheme: dark) {
  body.theme-auto {
    --bg-color: #121212;
    --text-color: #e0e0e0;
  }
}

换句话说,当系统指示默认主题为深色且用户选择了“自动”时,系统将自动应用深色。如果系统设置为浅色或未来的其他值,则主体将保留默认调色板。

用于将下拉菜单链接到主题并记住选择项的 JavaScript 代码可能如下所示:

document.addEventListener('DOMContentLoaded', () => {
  const select = document.getElementById('theme-select');
  const savedTheme = localStorage.getItem('theme') || 'theme-auto';

  document.body.classList.add(savedTheme);

  Array.from(select.options).forEach(option => {
    if (option.value === savedTheme) {
      option.selected = true;
    }
  });

  select.addEventListener('change', function () {
    document.body.classList.remove('theme-auto', 'theme-light', 'theme-dark');
    document.body.classList.add(this.value);
    localStorage.setItem('theme', this.value);
  });
});

只需编写少量额外代码,您就可以拥有 三种不同的模式根据系统提供浅色、深色和自动模式,并且由于以下原因,可以在两次访问之间保持设置: localStorage为了正确测试,您应该更改操作系统的主题设置,并在不同的浏览器中重新加载页面。

尊重系统和用户偏好

现代解决方案应该尝试 结合系统的总体偏好 (通过 prefers-color-scheme)由您所在位置的人明确决定(通过开关、选择器等控制)。一种非常常见的模式是:

首先,当页面加载完毕后,查看…… localStorage 如果已选择主题,则应用该主题。否则,您可以…… 使用媒体查询或 API 向浏览器发出请求 matchMedia 如果用户偏好深色或浅色,就从那里开始。

const userPreference = localStorage.getItem('theme');

if (userPreference) {
  document.documentElement.setAttribute('tema', userPreference);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
  document.documentElement.setAttribute('tema', 'dark');
} else {
  document.documentElement.setAttribute('tema', 'light');
}

然后,当对方与你的开关或菜单互动时, 您更新属性或类并保存新值 en localStorage这就是实现智能行为的方式:一开始要尊重系统,但一旦用户做出不同的决定,你的网站就会记住该决定并保持下去。

深色模式下的颜色、对比度和可访问性

安装开关固然有趣,但如果设计不够清晰易读,一切问题都将无从解决。在深色模式下,您必须特别注意背景和文字之间的对比度。对比度过低会导致阅读困难;对比度过高(例如纯白文字搭配纯黑色背景)则可能与设计糟糕的浅色主题一样令人疲劳,甚至更甚。

作为参考,WCAG 建议普通文本的对比度至少为4.5:1 ,如果需要更高的对比度,则建议使用 7:1。您无需手动计算:有很多在线工具和浏览器扩展程序可以告诉您配色方案是否符合要求,还可以检查高对比度模式等选项。

  你可以在 Movistar 上观看 HBO 吗?了解他们的服务

最好也避免使用纯白色(#ffffff)在纯黑色上(#000000例如,选择略微柔和的色调。 几乎全黑的背景#121212 以及非常浅灰色的文字,例如 #e0e0e0这样可以降低强烈的对比度,使整个画面更加赏心悦目。

选择合适的颜色方案、字体和用户界面元素

在深色模式下,高饱和度的颜色在深色背景下会非常显眼,因此最好使用低饱和度的色调来强调某些元素(例如按钮、链接、激活状态等)。您可以在变量中定义类似这样的内容:

:root {
  --color-acento: #bb86fc;
}

然后将其应用于链接和按钮:

a, button {
  color: var(--color-acento);
}

至于字体方面,它在深色主题下效果非常好。 稍微增大字体大小和行距。 给文本块留出一些空间。比如简单地把它们向上移动一点。 line-height 避免使用过细的字体就能提高可读性。

在界面设计中,务必确保按钮、输入框和交互控件与背景清晰区分:可以使用细微的边框、淡淡的阴影或鼠标悬停时的颜色变化。在深色模式下,悬停和聚焦效果对于指示哪些元素可以点击尤为重要,因此切勿忽略它们。

动画、动作和用户偏好

在主题切换时添加平滑过渡效果,可以使效果更加流畅自然,避免突兀感。添加过渡效果 背景和颜色 body 通常就足够了:

body {
  transition: background-color 0.3s ease, color 0.3s ease;
}

然而,并非每个人都喜欢动画,所以尊重个人喜好很重要。 prefers-reduced-motion当用户指定时,您可以缩短或取消过渡和动画的持续时间:

@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0ms !important;
    transition-duration: 0ms !important;
  }
}

这样一来,对动画动作敏感或容易晕动的用户就不会被迫忍受他们觉得烦人的效果,而其他用户仍然可以享受流畅的主题切换。

测试、兼容性和一些细节

主题系统设置完成后,接下来就是看似不起眼但却至关重要的部分:在各种浏览器和设备上进行测试。Chrome、Firefox 和 Safari 的开发者工具可以模拟系统深色模式和不同的屏幕密度;了解如何在 Opera 中强制启用深色主题也很有用。你还可以使用 Lighthouse 等工具来检查辅助功能和性能。

别忘了检查图片、图标和徽标。通常,深色徽标在白色背景上看起来很棒,但在深色背景下却会变得难以辨认。在这种情况下,您可以使用徽标的其他版本,或者应用滤镜和边框,使其在两种主题下都能清晰可见。

最后,最好征求真实的反馈意见:填写简短的表格、进行调查,甚至分析支持请求,都可以帮助您发现深色模式运行不佳、颜色组合有问题或元素尚未调整的情况。

这些要素定义清晰——结构良好的 CSS 变量、智能使用 prefers-color-scheme通过一些 JavaScript 和对对比度和可访问性的关注,用户控制功能得以实现,深色模式的实现不再令人头疼,而成为一项强大的改进,使您的网站更加舒适、现代,并符合访问者的期望。

Windows 11 更新暗黑模式
相关文章:
Windows 11 正在准备具有完整暗模式的更新。