3 行 CSS 代码实现暗黑模式及其他
暗黑模式是一种设计趋势,即将网站的配色方案更改为深色背景,并搭配浅色文本和元素。它也被称为夜间模式或暗黑主题。暗黑模式的目的是减少弱光环境下的眼睛疲劳,节省移动设备的电池寿命,并营造时尚现代的美感。
许多流行的网站和应用程序现在都提供了暗黑模式选项——这是 TailwindCSS:
如果您是开发人员,您很可能已经知道如何在开发工具中切换暗模式(对于那些不知道的人,请转到“渲染”选项卡!):
如果您想在操作系统(以及所有支持暗黑模式的应用)中启用暗黑模式,请前往“系统设置”。在 Mac 上,您可以在“系统设置”>“外观”下找到它:
目前已经有很多关于如何为网站实现暗模式的教程。
本教程将研究不同的方法,包括一些允许您抛弃 JavaScript 的全新 CSS 功能。
准备好了吗?我们开始吧。
使用系统颜色的暗模式
首先,我们将创建一个带有标题的简单 HTML 文档:
<body>
<h1>Hello Darkness, My Old Friend</h1>
</body>
在样式表中,我们将添加:
body {
color-scheme: light dark;
}
这将告诉浏览器,我们的文档可以接受亮色和暗色color-scheme
。
如果您在浏览器中运行此代码片段,即使打开了暗模式,它也会是……亮的。
不过,您的浏览器用户界面将会变暗。
这是因为用户代理样式表没有设置任何默认颜色。
我们可以通过使用系统颜色来快速解决这个问题:
body {
background-color: Canvas;
color: CanvasText;
color-scheme: light dark;
}
让我们再次检查一下代码片段:
好多了!只需3 行 CSS,即可为整个网站实现暗黑模式!
让我们更深入地了解一下系统颜色。从规格来看:
一般来说,
<system-color>
关键字反映了用户、浏览器或操作系统的默认颜色选择。因此,它们通常用于浏览器的默认样式表中。
以下是灯光模式演示,展示了 Safari 中可用的系统颜色:
如果我们切换到黑暗模式,一些颜色会完全改变(就像Canvas
我们CanvasText
已经遇到的那样),而其他颜色只会略有改变:
使用系统颜色来实现暗黑模式可以简化暗黑模式的体验。
是的,它会起作用——但是纯黑和纯白有点无聊。
我们可以用 CSS 来让它更有趣color-mix
。我们可以在 的 (白色或黑色) 中混合一点CanvasText
(黑色或白色) ,也可以在 的Canvas
(白色或黑色)中混合一点 (黑色或白色) :background-color
color
body {
background-color: color-mix(in srgb, Canvas, CanvasText 2.5%);
color: color-mix(in srgb, CanvasText, Canvas 15%);
}
这会产生一种“更柔和”的外观:
从颜色中扣除饱和度,是在黑暗模式下实现颜色变化的一种广泛使用的方法。
使用CSS 中的相对颜色,我们可以做到这一点:
background: hsl(from ActiveText h calc(s - 30%) l);
不幸的是,相对颜色目前还不能在任何浏览器中与系统颜色一起使用!
注意:系统颜色可以被强制颜色覆盖(尽管很少使用) - 所以不要过分依赖这种技术。
让我们继续讨论另一种技术,它将允许我们精细控制我们的暗模式颜色。
使用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);
}
然后,对于黑暗模式,我们只需更新这些颜色属性:
@media (prefers-color-scheme: dark) {
:where(body) {
--background-color: hsl(228, 5%, 15%);
--text-color: hsl(228, 5%, 80%);
}
}
让我们检查一下:
但是,如果我们希望用户独立于系统设置来选择他们想要的网站版本,该怎么办?
他们可能更喜欢将系统设置为暗模式,但我们的网站采用亮模式。
让我们创建一个切换器!
创建配色方案切换器
使用 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')
}
Open Props使用类似的方法,但更新的data-theme
是 -attribute,然后在两个块中定义属性:
[data-theme=light] {
--nav-icon: var(--gray-7); /* etc */
}
[data-theme=dark] {
--nav-icon: var(--gray-5); /* etc */
}
使用 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>
添加一些基本样式后(参见下面的 Codepen-demo),它呈现如下效果:
我们将向html 元素添加一个--darkmode
属性:container-type
html {
--darkmode: 0;
container-name: root;
container-type: normal;
}
我们将使用@container style()
-queries,因此我们需要将节点设置为“容器”。
因为我们不想观察inline-size
-变化,所以我们只需添加值normal
。
如果用户选择“强制”值,我们将更新--darkmode
:
html:has(#color-scheme-light:checked) { --darkmode: 0; }
html:has(#color-scheme-dark:checked) { --darkmode: 1; }
最后,我们将使用容器style()
查询来检查是否--darkmode
设置为1
:
@container root style(--darkmode: 1) {
body {
--background-color: hsl(228, 5%, 15%);
--text-color: hsl(228, 5%, 80%);
}
}
注意:
@container style()
-queries 目前仅在 Chrome 的标志后起作用,还处于早期阶段,因此请勿在生产中使用。
现在,选择“深色”后,我们的切换器(和页面)如下所示:
简单又有效!
存储状态
如果我们想存储用户的选择,恐怕我们需要一点 JavaScript!
首先,让我们添加一个标识符<fieldset>
:
<fieldset id="colorScheme">
然后,在 JavaScript 中:
const colorScheme = document.getElementById('colorScheme')
colorScheme.addEventListener('change', event => {
localStorage.setItem('color-scheme', event.target.value)
})
现在,我们要做的就是localStorage
在文档加载时将属性设置为-value:
window.addEventListener("load", event => {
const scheme = localStorage.getItem('color-scheme') || 'auto'
if (scheme) {
document.documentElement.style.setProperty('--darkmode', scheme)
}
})
要在切换器中选择正确的模式,请将其添加到if
-block:
const selected = [...colorScheme.elements].filter(element => element.value === scheme)
if (selected) selected[0].checked = true;
演示
切换器
系统颜色
照片提供:岛崎空
文章来源:https://dev.to/madsstoumann/dark-mode-in-3-lines-of-css-and-other-adventures-1ljj