3 行 CSS 代码实现暗黑模式及其他

2025-05-25

3 行 CSS 代码实现暗黑模式及其他

暗黑模式是一种设计趋势,即将网站的配色方案更改为深色背景,并搭配浅色文本和元素。它也被称为夜间模式暗黑主题。暗黑模式的目的是减少弱光环境下的眼睛疲劳,节省移动设备的电池寿命,并营造时尚现代的美感。

许多流行的网站和应用程序现在都提供了暗黑模式选项——这是 TailwindCSS:

Tailwind 配色方案选择器

如果您是开发人员,您很可能已经知道如何在开发工具中切换暗模式(对于那些不知道的人,请转到“渲染”选项卡!):

开发工具配色方案选择器

如果您想在操作系统(以及所有支持暗黑模式的应用)中启用暗黑模式,请前往“系统设置”。在 Mac 上,您可以在“系统设置”>“外观”下找到它:

MacOS 切换暗模式

目前已经有很多关于如何为网站实现暗模式的教程。

本教程将研究不同的方法,包括一些允许您抛弃 JavaScript 的全新 CSS 功能。

准备好了吗?我们开始吧。


使用系统颜色的暗模式

首先,我们将创建一个带有标题的简单 HTML 文档:

<body>
  <h1>Hello Darkness, My Old Friend</h1>
</body>
Enter fullscreen mode Exit fullscreen mode

在样式表中,我们将添加:

body {
  color-scheme: light dark;
}
Enter fullscreen mode Exit fullscreen mode

这将告诉浏览器,我们的文档可以接受亮色和暗色color-scheme

如果您在浏览器中运行此代码片段,即使打开了暗模式,它也会是……亮的。

不过,您的浏览器用户界面将会变暗。

浅色 深色

这是因为用户代理样式表没有设置任何默认颜色。

我们可以通过使用系统颜色来快速解决这个问题

body {
  background-color: Canvas;
  color: CanvasText;
  color-scheme: light dark;
}
Enter fullscreen mode Exit fullscreen mode

让我们再次检查一下代码片段:

带有系统颜色的暗模式

好多了!只需3 行 CSS,即可为整个网站实现暗黑模式!

让我们更深入地了解一下系统颜色。从规格来看:

一般来说,<system-color>关键字反映了用户、浏览器或操作系统的默认颜色选择。因此,它们通常用于浏览器的默认样式表中。

以下是灯光模式演示,展示了 Safari 中可用的系统颜色:

系统颜色

如果我们切换到黑暗模式,一些颜色会完全改变(就像Canvas我们CanvasText已经遇到的那样),而其他颜色只会略有改变:

黑暗模式下的系统颜色

使用系统颜色来实现暗黑模式可以简化暗黑模式的体验。

是的,它会起作用——但是纯黑和纯白有点无聊。

我们可以用 CSS 来让它更有趣color-mix。我们可以在 的 (白色或黑色) 中混合一点CanvasText(黑色或白色) ,也可以在 的Canvas(白色或黑色)中混合一点 (黑色或白色) background-colorcolor

body {
  background-color: color-mix(in srgb, Canvas, CanvasText 2.5%);
  color: color-mix(in srgb, CanvasText, Canvas 15%);
}
Enter fullscreen mode Exit fullscreen mode

这会产生一种“更柔和”的外观:

更柔和的黑暗模式

从颜色中扣除饱和度,是在黑暗模式下实现颜色变化的一种广泛使用的方法。

使用CSS 中的相对颜色,我们可以做到这一点:

background: hsl(from ActiveText h calc(s - 30%) l);
Enter fullscreen mode Exit fullscreen mode

不幸的是,相对颜色目前还不能在任何浏览器中与系统颜色一起使用!

注意:系统颜色可以被强制颜色覆盖(尽管很少使用) - 所以不要过分依赖这种技术。

让我们继续讨论另一种技术,它将允许我们精细控制我们的暗模式颜色。


使用prefers-color-scheme媒体查询

要为明暗模式指定特定颜色,我建议使用CSS 自定义属性,然后使用prefers-color-scheme媒体查询更新这些属性。

使用“灯光模式”作为默认模式,让我们将颜色添加到:where(body)“部分”,以将它们与常规body样式区分开:

/* Properties */
:where(body) {
  --background-color: #FFF;
  --text-color: #222;
}
body {
  background-color: var(--background-color);
  color: var(--text-color);
}
Enter fullscreen mode Exit fullscreen mode

然后,对于黑暗模式,我们只需更新这些颜色属性:

@media (prefers-color-scheme: dark) {
  :where(body) {
    --background-color: hsl(228, 5%, 15%);
    --text-color: hsl(228, 5%, 80%);
  }
}
Enter fullscreen mode Exit fullscreen mode

让我们检查一下:

带有媒体查询的黑暗模式

但是,如果我们希望用户独立于系统设置来选择他们想要的网站版本,该怎么办?

他们可能更喜欢将系统设置为暗模式,但我们的网站采用亮模式。

让我们创建一个切换器!


创建配色方案切换器

使用 JavaScript

如果你访问TailwindCSS之类的网站,你会注意到,当你在 color-scheme-toggler 中选择“dark”时,一个dark-class 会被添加到 -node 上。这是用 JavaScript 实现的:html

window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  document.documentElement.classList.add('dark')
} else {
  document.documentElement.classList.remove('dark')
}
Enter fullscreen mode Exit fullscreen mode

Open Props使用类似的方法,但更新的data-theme是 -attribute,然后在两个块中定义属性:

[data-theme=light] {
  --nav-icon: var(--gray-7); /* etc */
}
[data-theme=dark] {
  --nav-icon: var(--gray-5); /* etc */
}
Enter fullscreen mode Exit fullscreen mode

使用 CSS

使用一些全新的 CSS 技术,我们可以创建一个无需JavaScript 的切换器。

我们将创建一个具有 3 个状态的切换器:

  • 轻度(强制)
  • 自动(系统默认,可以是亮的也可以是暗的)
  • 黑暗(强制)

首先,一些基本的标记:

<fieldset>
  <label>
    <input type="radio" name="color-scheme" id="color-scheme-light" value="0">
    Light
  </label>
  <label>
    <input type="radio" name="color-scheme" value="auto" checked>
    Auto
  </label>
  <label>
    <input type="radio" name="color-scheme" id="color-scheme-dark" value="1">
    Dark
  </label>
</fieldset>
Enter fullscreen mode Exit fullscreen mode

添加一些基本样式后(参见下面的 Codepen-demo),它呈现如下效果:

基本暗模式切换器

我们将向html 元素添加一个--darkmode属性:container-type

html {
  --darkmode: 0;
  container-name: root;
  container-type: normal;
}
Enter fullscreen mode Exit fullscreen mode

我们将使用@container style()-queries,因此我们需要将节点设置为“容器”。

因为我们不想观察inline-size-变化,所以我们只需添加值normal

如果用户选择“强制”值,我们将更新--darkmode

html:has(#color-scheme-light:checked) { --darkmode: 0; }
html:has(#color-scheme-dark:checked) { --darkmode: 1; }
Enter fullscreen mode Exit fullscreen mode

最后,我们将使用容器style()查询来检查是否--darkmode设置为1

@container root style(--darkmode: 1) {
  body {
    --background-color: hsl(228, 5%, 15%);
    --text-color: hsl(228, 5%, 80%);
  }
}
Enter fullscreen mode Exit fullscreen mode

注意: @container style() -queries 目前仅在 Chrome 的标志后起作用,还处于早期阶段,因此请勿在生产中使用。

现在,选择“深色”后,我们的切换器(和页面)如下所示:

黑暗模式下的切换器

简单又有效!


存储状态

如果我们想存储用户的选择,恐怕我们需要一点 JavaScript!

首先,让我们添加一个标识符<fieldset>

<fieldset id="colorScheme">
Enter fullscreen mode Exit fullscreen mode

然后,在 JavaScript 中:

const colorScheme = document.getElementById('colorScheme')
colorScheme.addEventListener('change', event => {
  localStorage.setItem('color-scheme', event.target.value)
})
Enter fullscreen mode Exit fullscreen mode

现在,我们要做的就是localStorage在文档加载时将属性设置为-value:

window.addEventListener("load", event => {
  const scheme = localStorage.getItem('color-scheme') || 'auto'
  if (scheme) {
    document.documentElement.style.setProperty('--darkmode', scheme)
  }
})
Enter fullscreen mode Exit fullscreen mode

要在切换器中选择正确的模式,请将其添加到if-block:

const selected = [...colorScheme.elements].filter(element => element.value === scheme)
if (selected) selected[0].checked = true;
Enter fullscreen mode Exit fullscreen mode

演示

切换器

系统颜色


照片提供:岛崎空

文章来源:https://dev.to/madsstoumann/dark-mode-in-3-lines-of-css-and-other-adventures-1ljj
PREV
更新一个已有 25 年历史的网站
NEXT
创建一个有趣、快速、安全且可持续的网站