暗黑模式最近获得了很大关注。 例如,Apple 已将其 iOS 和 MacOS 操作系统添加了暗黑模式。 Windows 和 Google 也一样。
让我们从 **网站** 的角度深入了解暗黑模式。 我们将深入探讨实现暗黑模式设计的不同选项和方法,以及它们带来的技术考虑因素。 我们还将介绍一些设计技巧。
切换主题
典型情况是您已经为您的网站创建了一个亮色主题,并且您希望创建一个更暗的对应主题。 或者,即使您从头开始,您也会有两种主题:亮色和暗黑。 其中一个主题应被定义为用户首次访问时获得的默认主题,在大多数情况下是亮色主题(尽管我们可以让用户的浏览器为我们做出这个选择,正如我们将在后面看到的那样)。 还应该有一种方法可以切换到另一个主题(这可以自动完成,正如我们也将看到的那样)——例如,用户点击一个按钮,颜色主题就会发生变化。
有多种方法可以实现这一点
使用 Body 类
这里的诀窍是替换一个类,它可以作为页面上任何位置更改样式的钩子。
<body class="dark-theme || light-theme">
例如,这里是一个用于切换该类的按钮的脚本
// Select the button
const btn = document.querySelector('.btn-toggle');
// Listen for a click on the button
btn.addEventListener('click', function() {
// Then toggle (add/remove) the .dark-theme class to the body
document.body.classList.toggle('dark-theme');
})
以下是我们可以使用该想法的方法
<body>
<button class="btn-toggle">Toggle Dark Mode</button>
<h1>Hey there! This is just a title</h1>
<p>I am just a boring text, existing here solely for the purpose of this demo</p>
<p>And I am just another one like the one above me, because two is better than having only one</p>
<a href="#">I am a link, don't click me!</a>
</body>
这种方法的基本思路是像往常一样设置样式,将其称为我们的“默认”模式,然后使用一个在<body>
元素上设置的类创建一个完整的颜色样式集,我们可以将其用作“暗黑”模式。
假设我们的默认主题是亮色方案。 所有这些“亮色”样式都以您通常编写 CSS 的方式编写。 鉴于我们的 HTML,让我们将一些全局样式应用于 body 和链接。
body {
color: #222;
background: #fff;
}
a {
color: #0033cc;
}
很好。 我们在亮色背景 (#fff
) 上有深色文本 (#222
) 和深色链接 (#0033cc
)。 我们的“默认”主题已经取得了一个良好的开端。
现在让我们重新定义这些属性值,这次将其设置在不同的 body 类上
body {
color: #222;
background: #fff;
}
a {
color: #0033cc;
}
/* Dark Mode styles */
body.dark-theme {
color: #eee;
background: #121212;
}
body.dark-theme a {
color: #809fff;
}
暗黑主题样式将是相同父类的后代——在本例中是.dark-theme
——我们已将其应用于<body>
标签。
我们如何“切换”body 类以访问暗黑样式? 我们可以使用 JavaScript! 我们将选择按钮类 (.btn-toggle
),添加一个点击监听器,然后将暗黑主题类 (.dark-theme
) 添加到 body 元素的类列表中。 由于级联和特异性,这实际上会覆盖我们设置的所有“亮色”,
以下是完整的代码在实际操作中的演示。 点击切换按钮以在暗黑模式和亮色模式之间切换。
使用单独的样式表
我们无需将所有样式保留在一个样式表中,而是可以为每个主题切换样式表。 这假设您已经准备好了完整的样式表。
例如,一个默认的亮色主题,比如light-theme.css
/* light-theme.css */
body {
color: #222;
background: #fff;
}
a {
color: #0033cc;
}
然后,我们创建暗黑主题的样式,并将它们保存到一个我们称之为dark-theme.css
的单独样式表中。
/* dark-theme.css */
body {
color: #eee;
background: #121212;
}
body a {
color: #809fff;
}
这为我们提供了两个独立的样式表——每个主题一个——我们可以将其链接到 HTML 的<head>
部分中。 让我们先链接亮色样式,因为我们将其称为默认样式。
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Light theme stylesheet -->
<link href="light-theme.css" rel="stylesheet" id="theme-link">
</head>
<!-- etc. -->
</html>
我们使用一个#theme-link
ID,我们可以使用 JavaScript 选择它,再次在亮色模式和暗黑模式之间切换。 只是这次,我们切换的是文件而不是类。
// Select the button
const btn = document.querySelector(".btn-toggle");
// Select the stylesheet <link>
const theme = document.querySelector("#theme-link");
// Listen for a click on the button
btn.addEventListener("click", function() {
// If the current URL contains "ligh-theme.css"
if (theme.getAttribute("href") == "light-theme.css") {
// ... then switch it to "dark-theme.css"
theme.href = "dark-theme.css";
// Otherwise...
} else {
// ... switch it to "light-theme.css"
theme.href = "light-theme.css";
}
});
使用自定义属性
我们也可以利用 CSS 自定义属性的强大功能来创建暗黑主题! 它可以帮助我们避免为每个主题编写单独的样式规则集,从而使编写样式变得更快,并且如果需要更改主题,也更容易进行更改。
我们仍然可以选择切换 body 类,并使用该类重新设置自定义属性
// Select the button
const btn = document.querySelector(".btn-toggle");
// Listen for a click on the button
btn.addEventListener("click", function() {
// Then toggle (add/remove) the .dark-theme class to the body
document.body.classList.toggle("dark-theme");
});
首先,让我们将默认亮色值定义为 body 元素上的自定义属性
body {
--text-color: #222;
--bkg-color: #fff;
--anchor-color: #0033cc;
}
现在,我们可以像在第一种方法中一样,在一个.dark-theme
body 类上重新定义这些值
body.dark-theme {
--text-color: #eee;
--bkg-color: #121212;
--anchor-color: #809fff;
}
以下是我们使用自定义属性的 body 和链接元素的规则集
body {
color: var(--text-color);
background: var(--bkg-color);
}
a {
color: var(--anchor-color);
}
我们也可以在文档的:root
中定义我们的自定义属性。 这完全合法,而且 甚至是一种常见的做法。 在这种情况下,所有默认主题样式定义都将进入:root { }
,而所有暗黑主题属性都将进入:root.dark-mode { }
。
使用服务器端脚本
如果我们正在使用服务器端语言,例如 PHP,那么我们可以使用它而不是 JavaScript。 如果您更喜欢直接在标记中工作,这是一种很好的方法。
<?php
$themeClass = '';
if (isset($_GET['theme']) && $_GET['theme'] == 'dark') {
$themeClass = 'dark-theme';
}
$themeToggle = ($themeClass == 'dark-theme') ? 'light' : 'dark';
?>
<!DOCTYPE html>
<html lang="en">
<!-- etc. -->
<body class="<?php echo $themeClass; ?>">
<a href="?theme=<?php echo $themeToggle; ?>">Toggle Dark Mode</a>
<!-- etc. -->
</body>
</html>
我们可以让用户发送一个GET
或POST
请求。 然后,我们让我们的代码(在本例中是 PHP)在页面重新加载时应用相应的 body 类。 出于演示目的,我正在使用GET
请求(URL 参数)。
当然,我们也可以像在第二种方法中一样交换样式表。
<?php
$themeStyleSheet = 'light-theme.css';
if (isset($_GET['theme']) && $_GET['theme'] == 'dark') {
$themeStyleSheet = 'dark-theme.css';
}
$themeToggle = ($themeStyleSheet == 'dark-theme.css') ? 'light' : 'dark';
?>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- etc. -->
<link href="<?php echo $themeStyleSheet; ?>" rel="stylesheet">
</head>
<body>
<a href="?theme=<?php echo $themeToggle; ?>">Toggle Dark Mode</a>
<!-- etc. -->
</body>
</html>
这种方法有一个明显的缺点:页面需要刷新才能切换。 但是,这种服务器端解决方案对于在页面重新加载时保持用户主题选择非常有用,正如我们将在后面看到的那样。
应该选择哪种方法?
“正确”的方法取决于您的项目的具体要求。 例如,如果您正在进行一个大型项目,那么您可能可以选择 CSS 属性来帮助管理一个大型代码库。 另一方面,如果您的项目需要支持旧版浏览器,那么将需要使用其他方法。
此外,并没有规定我们只能使用一种方法。 有时候,多种方法的组合将是最有效的方法。 甚至可能存在我们尚未讨论的其他可能方法。
操作系统级别的暗黑模式
到目前为止,我们一直在使用按钮在亮色模式和暗黑模式之间切换,但我们可以简单地让用户的操作系统为我们完成这项工作。 例如,许多操作系统允许用户直接在系统设置中选择亮色和暗黑主题。
纯 CSS
细节
幸运的是,CSS 有一个prefers-color-scheme
媒体查询,可以用来检测用户的系统颜色方案偏好。 它可以有三个可能的值:无偏好、亮色和暗黑。 在 MDN 上了解更多信息 MDN。
@media (prefers-color-scheme: dark) {
/* Dark theme styles go here */
}
@media (prefers-color-scheme: light) {
/* Light theme styles go here */
}
要使用它,我们可以将深色主题样式放在媒体查询中。
@media (prefers-color-scheme: dark) {
body {
color: #eee;
background: #121212;
}
a {
color: #809fff;
}
}
现在,如果用户从系统设置中启用了深色模式,他们将默认获得深色模式样式。我们无需使用 JavaScript 或服务器端脚本来决定使用哪种模式。实际上,我们甚至不再需要按钮了!
JavaScript
细节
我们可以使用 JavaScript 来检测用户的首选配色方案。这很像我们使用过的第一种方法,只是我们使用 matchedMedia()
来检测用户的偏好。
const prefersDarkScheme = window.matchMedia('(prefers-color-scheme: dark)');nnif (prefersDarkScheme.matches) {n document.body.classList.add('dark-theme');n} else {n document.body.classList.remove('dark-theme');n}
使用 JavaScript 的缺点是:由于 JavaScript 在 CSS 之后执行,因此可能会出现浅色主题的快速闪烁。这可能会被误认为是 bug。
当然,我们可以像在第二种方法中那样交换样式表。这次,我们链接了两个样式表,并使用媒体查询来确定应用哪一个。
覆盖操作系统设置
我们刚刚了解了如何考虑用户的系统范围内的配色方案偏好。但是,如果用户想覆盖他们在网站上的系统偏好怎么办? 仅仅因为用户喜欢他们操作系统的深色模式,并不一定意味着他们也喜欢网站上的深色模式。因此,提供一种方法来手动覆盖深色模式,即使系统设置也如此,是一个好主意。
查看代码
让我们使用 CSS 自定义属性方法来演示如何做到这一点。思路是像以前一样定义两种主题的自定义属性,将深色样式包装在 prefers-color-scheme
媒体查询中,然后在其中定义一个 .light-theme
类,如果用户想在两种模式之间切换,可以使用该类来覆盖深色模式属性。
/* Default colors */
body {
--text-color: #222;
--bkg-color: #fff;
}
/* Dark theme colors */
body.dark-theme {
--text-color: #eee;
--bkg-color: #121212;
}
/* Styles for users who prefer dark mode at the OS level */
@media (prefers-color-scheme: dark) {
/* defaults to dark theme */
body {
--text-color: #eee;
--bkg-color: #121212;
}
/* Override dark mode with light mode styles if the user decides to swap */
body.light-theme {
--text-color: #222;
--bkg-color: #fff;
}
}
现在我们可以回到我们可靠的按钮来切换浅色和深色主题。这样,我们默认情况下尊重操作系统颜色偏好,并允许用户手动切换主题。
// Listen for a click on the button
btn.addEventListener("click", function() {
// If the OS is set to dark mode...
if (prefersDarkScheme.matches) {
// ...then apply the .light-theme class to override those styles
document.body.classList.toggle("light-theme");
// Otherwise...
} else {
// ...apply the .dark-theme class to override the default light styles
document.body.classList.toggle("dark-theme");
}
});
浏览器支持
prefers-color-scheme
媒体查询功能得到了主要浏览器的支持,包括 Chrome 76+、Firefox 67+、Chrome Android 76+、Safari 12.5+(iOS 上为 13+)和三星互联网浏览器。它不支持 IE。
这是一个很有希望的支持量!Can I Use 估计用户覆盖率为 80.85%。
目前支持深色模式的操作系统包括 MacOS(Mojave 或更高版本)、iOS(13.0+)、Windows(10+)和 Android(10+)。
存储用户的偏好
到目前为止,我们所看到的内容肯定做到了它的宣传:根据操作系统偏好或按钮点击来切换主题。这很好,但当用户访问网站上的另一个页面或重新加载当前页面时,它不会延续。
我们需要保存用户的选择,以便在整个网站和后续访问中一致地应用它。为此,我们可以在主题切换时将用户的选择保存到 localStorage
中。Cookie 也非常适合这项工作。
让我们看看这两种方法。
使用 localStorage
我们有一个脚本,当切换发生时,它将选定的主题保存到 localStorage 中。换句话说,当页面重新加载时,脚本从 localStorage
中获取选择并应用它。JavaScript 通常在 CSS 之后执行,因此这种方法容易出现“错误主题闪烁”(FOIT)。
查看代码
// Select the button
const btn = document.querySelector(".btn-toggle");
// Select the theme preference from localStorage
const currentTheme = localStorage.getItem("theme");
// If the current theme in localStorage is "dark"...
if (currentTheme == "dark") {
// ...then use the .dark-theme class
document.body.classList.add("dark-theme");
}
// Listen for a click on the button
btn.addEventListener("click", function() {
// Toggle the .dark-theme class on each click
document.body.classList.toggle("dark-theme");
// Let's say the theme is equal to light
let theme = "light";
// If the body contains the .dark-theme class...
if (document.body.classList.contains("dark-theme")) {
// ...then let's make the theme dark
theme = "dark";
}
// Then save the choice in localStorage
localStorage.setItem("theme", theme);
});
使用 PHP 和 Cookie
为了避免 FLIC,我们可以使用 PHP 之类的服务器端脚本。我们不会将用户的主题偏好保存在 localStorage
中,而是会从 JavaScript 创建一个 cookie 并将其保存到那里。但同样,这可能只有在您已经使用服务器端语言时才可行。
查看代码
// Select the button
const btn = document.querySelector(".btn-toggle");
// Listen for a click on the button
btn.addEventListener("click", function() {
// Toggle the .dark-theme class on the body
document.body.classList.toggle("dark-theme");
// Let's say the theme is equal to light
let theme = "light";
// If the body contains the .dark-theme class...
if (document.body.classList.contains("dark-theme")) {
// ...then let's make the theme dark
theme = "dark";
}
// Then save the choice in a cookie
document.cookie = "theme=" + theme;
});
我们现在可以检查该 cookie 是否存在,并通过将适当的类应用于 <body>
标签来加载相应的主题。
<?php
$themeClass = '';
if (!empty($_COOKIE['theme']) && $_COOKIE['theme'] == 'dark') {
$themeClass = 'dark-theme';
}
?>
<!DOCTYPE html>
<html lang="en">
<!-- etc. -->
<body class="<?php echo $themeClass; ?>">
<!-- etc. -->
</body>
</html>
以下是如何使用单独样式表方法来实现。
<?php
$themeStyleSheet = 'light-theme.css';
if (!empty($_COOKIE['theme']) && $_COOKIE['theme'] == 'dark') {
$themeStyleSheet = 'dark-theme.css';
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- etc. -->
<link href="<?php echo $themeStyleSheet; ?>" rel="stylesheet" id="theme-link">
</head>
<!-- etc. -->
如果您的网站有用户帐户 - 比如登录和管理个人资料信息的地方 - 那里也是保存主题偏好的好地方。将其发送到存储用户帐户详细信息的数据库。然后,当用户登录时,从数据库中获取主题,并使用 PHP(或任何服务器端脚本)将其应用到页面。
有多种方法可以做到这一点。在本例中,我在登录时从数据库中获取用户的主题偏好,并将其保存在一个会话变量中。
<?php
// Login action
if (!empty($_POST['login'])) {
// etc.
// If the uuser is authenticated...
if ($loginSuccess) {
// ... save their theme preference to a session variable
$_SESSION['user_theme'] = $userData['theme'];
}
}
// Pick the session variable first if it's set; otherwise pick the cookie
$themeChoice = $_SESSION['user_theme'] ?? $_COOKIE['theme'] ?? null;
$themeClass = '';
if ($themeChoice == 'dark') {
$themeClass = 'dark-theme';
}
?>
<!DOCTYPE html>
<html lang="en">
<!-- etc. -->
<body class="<?php echo $themeClass; ?>">
<!-- etc. -->
</body>
</html>
我正在使用 PHP 的 null 合并运算符(??
)来决定从哪里获取主题偏好:从会话还是从 cookie 中。如果用户已登录,则使用会话变量的值,而不是 cookie 的值。如果用户未登录或已注销,则使用 cookie 的值。
处理用户代理样式
为了告知浏览器 UA 样式表系统颜色方案偏好,并告诉它页面中支持哪些颜色方案,我们可以使用 color-scheme
元标签。
例如,假设页面应该支持“深色”和“浅色”两种主题。我们可以将它们都作为值放在元标签中,用空格隔开。如果我们只希望支持“浅色”主题,那么我们只需要使用“浅色”作为值即可。这在 CSSWG GitHub 问题 中进行了讨论,最初是在这里提出的。
<meta name="color-scheme" content="dark light">
当添加此元标签时,浏览器会在渲染页面中 UA 控制的元素(如 <button>
)时考虑用户的颜色方案偏好。它会根据用户的偏好渲染根背景、表单控件和拼写检查功能(以及任何其他 UA 控制的样式)的颜色。
虽然主题在很大程度上是手动设置样式的(这会覆盖 UA 样式),但告知浏览器支持的主题有助于避免出现即使是最轻微的潜在 FOIT 情况。对于 HTML 已经渲染但 CSS 仍在等待加载的那些情况,这是正确的。
我们也可以在 CSS 中设置它
:root {
color-scheme: light dark; /* both supported */
}
在撰写本文时,color-scheme
属性 缺乏广泛的浏览器支持,尽管 Safari 和 Chrome 都支持它。
结合所有内容!
让我们将所有内容结合起来,创建一个工作演示,它
- 根据系统偏好自动加载深色或浅色主题
- 允许用户手动覆盖其系统偏好
- 在页面重新加载时保留用户首选的主题
使用 JavaScript 和 Local Storage
// Select the button
const btn = document.querySelector(".btn-toggle");
// Check for dark mode preference at the OS level
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
// Get the user's theme preference from local storage, if it's available
const currentTheme = localStorage.getItem("theme");
// If the user's preference in localStorage is dark...
if (currentTheme == "dark") {
// ...let's toggle the .dark-theme class on the body
document.body.classList.toggle("dark-mode");
// Otherwise, if the user's preference in localStorage is light...
} else if (currentTheme == "light") {
// ...let's toggle the .light-theme class on the body
document.body.classList.toggle("light-mode");
}
// Listen for a click on the button
btn.addEventListener("click", function() {
// If the user's OS setting is dark and matches our .dark-mode class...
if (prefersDarkScheme.matches) {
// ...then toggle the light mode class
document.body.classList.toggle("light-mode");
// ...but use .dark-mode if the .light-mode class is already on the body,
var theme = document.body.classList.contains("light-mode") ? "light" : "dark";
} else {
// Otherwise, let's do the same thing, but for .dark-mode
document.body.classList.toggle("dark-mode");
var theme = document.body.classList.contains("dark-mode") ? "dark" : "light";
}
// Finally, let's save the current preference to localStorage to keep using it
localStorage.setItem("theme", theme);
});
使用 PHP 和 Cookie
<?php
$themeClass = '';
if (!empty($_COOKIE['theme'])) {
if ($_COOKIE['theme'] == 'dark') {
$themeClass = 'dark-theme';
} else if ($_COOKIE['theme'] == 'light') {
$themeClass = 'light-theme';
}
}
?>
<!DOCTYPE html>
<html lang="en">
<!-- etc. -->
<body class="<?php echo $themeClass; ?>">
<!-- etc. -->
<script>
const btn = document.querySelector(".btn-toggle");
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
btn.addEventListener("click", function() {
if (prefersDarkScheme.matches) {
document.body.classList.toggle("light-mode");
var theme = document.body.classList.contains("light-mode") ? "light" : "dark";
} else {
document.body.classList.toggle("dark-mode");
var theme = document.body.classList.contains("dark-mode") ? "dark" : "light";
}
document.cookie = "theme=" + theme;
});
</script>
</body>
</html>
设计注意事项
我经常听到人们说,实现深色模式比设计深色模式更容易。虽然我不会妄加评论,但让我们来看看设计深色主题的一些注意事项。
您已经知道基本任务:将较浅的颜色值替换为较深的颜色值,反之亦然。但是,有一些 UI 元素和增强功能更加细致,需要更多关注。让我们来看看这些。
深色模式图像
一个好的规则是稍微降低图像的亮度和对比度,这样在深色背景下观看时会更舒适。在超深色背景上放置超亮图像可能会令人不适,而调暗图像可以减少一些强烈的对比度。
CSS 的 filter()
函数完全能够为我们处理这个问题
/* Apply the filter directly on the body tag */
body.dark-theme img {
filter: brightness(.8) contrast(1.2);
}
/* Or apply it via media query */
@media (prefers-color-scheme: dark) {
img {
filter: brightness(.8) contrast(1.2);
}
}
我们可以在标记中直接使用 <picture>
元素来加载图像的不同版本,从而实现类似的效果。
<picture>
<!-- Use this image if the user's OS setting is light or unset -->
<source srcset="photo-light.png" media="(prefers-color-scheme: light) or (prefers-color-scheme: no-preference)">
<!-- Use this image if the user's OS setting is dark -->
<source srcset="photo-dark.png" media="(prefers-color-scheme: dark)">
</picture>
这样做的缺点是,我们需要提供两个文件,而使用 CSS 时只需要处理一个文件。这也不能完全解决用户在网站上切换颜色主题的问题。
深色模式阴影
深色模式阴影很棘手。如果我们只是用浅色反转深色阴影,那么我们会得到一个奇怪的东西,即深色背景上有一个浅色阴影……这不好看。
在深色模式中使用深色阴影是可能的,但背景颜色必须“足够浅”(比如深灰色),才能提供足够的对比度,以便在背景上看到阴影。
🔥 在实现深色模式时,不要通过简单地反转颜色方案来抛弃浅色版本中的视觉提示。
— Steve Schoger (@steveschoger) 2019 年 7 月 16 日
即使在深色 UI 中,靠近的元素也应该更亮,而较远的元素应该更暗。pic.twitter.com/RNxgIppDmn
使用不透明度来传达深度,不透明度较高的区域具有较低的深度。也就是说,具有较高海拔的元素应该具有比“更靠近”背景的元素更低的不透明度。
深色模式排版
这里的诀窍很像图像:我们必须平衡对比度。使用太重的字体会导致刺眼的文本,让我们想要远离屏幕。使用太轻的字体会导致我们眯起眼睛,同时向屏幕靠近以看得更清楚。
平衡点介于两者之间。Robin 有一篇很好的文章,他建议使用一些简单的 CSS 代码,这对于可读性有很大帮助。
深色模式图标
图标属于“棘手”类别,因为它们有点介于文本和图像之间。但是,如果我们使用 SVG 图标,我们可以使用 CSS 更改填充。另一方面,如果我们使用字体图标,我们可以简单地更改颜色属性。
/* SVG icon */
body.dark-theme svg.icon path {
fill: #efefef;
}
/* Font icon (using Font Awesome as an example) */
body.dark-theme .fa {
color: #efefef;
}
文本的大多数设计注意事项通常也适用于图标。例如,我们应该避免使用纯白色和粗重的轮廓。
深色模式颜色
纯白色文本在纯黑色背景上看起来会很刺眼。这里的诀窍是使用淡白色作为文本,使用淡黑色作为背景。Material Design 指南 例如建议将 #121212
用于背景。
深色模式调色板
我们已经看到了使用淡白色和淡黑色会对文本和图像造成的影响。让我们进一步探讨一些关于如何开发完整调色板的提示。
大多数事情归结为一点:对比度。这就是为什么在确定任何颜色之前,第一个提示是将想法通过对比度检查器来运行,以确保颜色比率符合 WCAG 的至少 AA 等级指南,即 4.5:1 的对比度比率。
这意味着在使用深色模式设计时,非饱和色是我们的朋友。它们有助于防止过于明亮的图像,并且仍然为我们提供了足够的空间来创建有效的对比度比率。
接下来,请记住,强调色是用来增强的。它们可能比深色主题背景色更亮,因此将它们用作主色或大型容器的背景色,就像明亮的图像或浓重的白色文本一样,会让人不适,并且对眼睛有压力。
如果对比度是我们试图取得的平衡,那么请记住,深色模式不仅仅是黑色和灰色。深蓝色背景配淡黄色文本怎么样?或者深棕色配米色?那里有整个(并且不断增长)的颜色频谱,我们可以利用它的任何部分来激发创造力。
一些深色而不使用全黑的颜色的例子
#232B32
#152028
#202945
Material Design 关于深色模式的指南 是深色模式设计最佳实践的实用资源。它绝对值得一读,可以了解更多需要记住的提示。
深色模式在现实中的应用
YouTube 使用 CSS 变量技术。他们在 html 选择器下定义了所有颜色变量,而深色模式颜色则在 html:not(.style-scope)[dark]
下定义。启用深色模式时,YouTube 会在 <html>
标签中添加 dark="true"
属性。这就是他们用来覆盖 HTML 中定义的变量的方法。
在现实中,CSS 自定义属性方法似乎最受欢迎。Dropbox Paper、Slack 和 Facebook 都在使用它。
Simplenote 使用类交换方法,所有浅色样式规则都是 .theme-light
父类的后代,所有深色样式都属于 .theme-dark
类。当主题切换时,相应的类将应用于 <body>
标签。
Twitter 更进一步,提供了多种主题可供选择:“默认”、“昏暗”和“熄灯”。“昏暗”选项使用深蓝色作为背景色。与使用纯黑色的“熄灯”相比。
深色模式还是不深色模式?这是一个问题。
双方都有充分的理由。其中一些原因甚至超出了用户体验的范围,包括时间、预算和资源等方面。
在考虑为什么您可能不想实现深色模式的同时,以下是一些您可能想要使用深色模式的原因。
- 它很酷,很流行(虽然这不能作为唯一的理由)。
- 它通过支持对刺眼的明亮主题敏感的用户,来增强可访问性。
- 它允许用户决定最舒适的消费内容方式,同时为我们提供了一种方法来控制事物的视觉效果。请记住,我们想要击败阅读模式按钮!
- 它有助于延长配备 OLED 屏幕的设备的电池续航时间,因为更明亮的颜色会消耗更多能量。
- 它非常受欢迎,而且似乎不会消失。您喜欢深色模式的用户(比如我!)可能会期望您的网站也有深色模式。最好做好准备。
同样值得一提的是,开发者工具提供了一个选项,可以切换深色和浅色模式,而无需更改操作系统,如果你想检查你的检测是否有效。
在基于 Chromium 的浏览器(Microsoft Edge/Chrome/Brave…)中,你可以在渲染菜单中进行此操作,或者使用键盘快捷键。
https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/accessibility/preferred-color-scheme-simulation
是的!这将非常方便。
这篇文章有一个主要问题:所有描述的选项都需要 JavaScript 才能生效。
一种**更好**的客户端解决深色模式的技术是使用实际的媒体查询,然后让你的切换修改媒体查询,而不是添加或删除类。
最终的结果是,即使禁用 JavaScript,深色模式也能正常工作,而且你获得错误主题闪烁的可能性比以前更小。
我在自己的网站上使用了这种技术,并在 https://chrismorgan.info/blog/dark-theme-implementation/ 上写了关于它的文章。
还有一件事:这个例子是错误的。
<picture>
必须有一个<img>
子节点,这样如果没有任何源匹配,仍然会有东西显示。按照目前的情况,不支持(prefers-color-scheme)
的旧浏览器将根本不会显示图像。此外,将来可能会添加更多值;所以not all and (prefers-color-scheme: dark)
比(prefers-color-scheme: light)
更好。(顺便说一下,no-preference
已从规范中删除;UA 现在默认为light
。)因此,示例应该改为:
嘿,Chris,
这是一个有趣的技术。感谢分享。:)
不幸的是,我不太明白这到底是如何防止FLIC 情况的,因为你仍然需要使用 JavaScript 来修改查询等等。也许是我遗漏了什么?!
这篇文章确实谈到了使用
prefers-color-scheme
媒体查询来适应系统偏好——即使禁用 JS 也应该可以工作。但仍然,当你需要让用户手动控制他们的主题偏好时,JS 就派上用场了(即覆盖系统偏好)。你说得对
<picture>
。这看起来好多了!感谢你指出。为什么这篇文章没有深色模式选项?呸…:)
不。**这**是深色模式。
https://tonsky.me
:)
这确实是一个巧妙的深色模式实现!
这是我见过的最棒的深色模式 :-)
非常棒且详细的文章!:)
我认为它缺少使用纯 CSS 切换主题的方法。这可能会有用,因为并非每个人都能访问 JavaScript,或者仅仅是为了好玩!
我之前写过一篇关于如何实现此目的的文章,对一些读者来说可能很有趣:https://alexandersandberg.com/theme-switcher/
这是源代码:https://github.com/alexandersandberg/theme-switcher
它是一种使用复选框(如果超过 2 个主题则使用单选按钮)和一些 CSS 选择器魔法来切换主题的技术。它也是可访问的,这是一个巨大的优势。
遗憾的是,为了存储用户的主题偏好,仍然需要一点 JavaScript。
那里有一篇非常棒的综合性文章,伙计!
不幸的是,“结合所有东西!”演示在 Firefox 中有效,但在 Chrome 中无效。
我已经将操作系统设置为深色模式(以防它是问题的一部分)。
我的想法:[浅色和深色模式,带用户切换按钮](https://codepen.io/2kool2/pen/abzgPzJ)
对于一份“完整”指南来说,高对比度模式缺失了。强制颜色查询在这里是我们的朋友。
简单地将其称为超深色模式,一个 a11y 主题听起来很酷,并且适合这篇文章。
很棒的文章,我喜欢 CSS 技巧!
我写了一篇关于如何使用 React 和 React Hooks 以及样式化组件来实现深色模式的博客文章。
如果你觉得有用,可以查看这篇文章 here。
一些我保存的深色模式链接……
你的纯 CSS 方法在我的 iPhone 上的 Safari 中完美运行。不知道为什么第二个示例,JavaScript,没有运行。我的浏览器没有禁用任何东西。无论如何,我感谢这篇简洁的文章!
JavaScript 示例不起作用,因为它无法像代码编写方式那样自行检测主题更改。类切换部分只会在运行一次。要每次主题更改时切换,将类切换代码添加到 “onchange” 事件的 “prefersDarkScheme” 对象中作为回调函数,一切将正常运行。
请您编写代码吗?
这样我们就可以从设备切换多次)
另外,我很好奇为什么 css-tricks 仍然没有这个功能,让用户手动切换..((
嗨!非常有帮助的文章。我现在正在尝试在我的网站上添加夜间模式,但在存储用户的偏好时遇到了困难。
在文章中,使用 localStorage 存储用户的偏好只适用于方法 #1“使用 body 类”,但如何使其适用于方法 #2“使用单独的样式表”?
我正在尝试这样做,但没有任何变化,因为我对 JS 的了解非常有限。你能帮我吗?
很棒的文章!
我在我的 WordPress 网站上应用了 cookie 和服务器端技术。这非常有效——直到我激活了页面缓存。
网站显然从页面缓存中受益匪浅,但这意味着主题没有“存储”,例如,对于每个新页面,你都会从缓存版本开始,重新开始。
所以我想知道是否还有其他不使用 FOIT 的 JavaScript 方法。因为标签是在遇到时执行的,我的一个想法是在加载整个页面之前添加一个标签,该标签获取 cookie 值,并在需要时添加类。你知道这样的方法是否可行吗?
非常感谢!
Ralph
这可能与深色模式无关。但是有人可以告诉我演示中使用的工具是什么,它可以让你滑动垂直栏以查看左右对比?我认为这是一个非常酷的演示效果。
我相信这个页面上的工具是基于 Juxtapose(https://juxtapose.knightlab.com)的,但网上还有很多这样的前后滑动工具,比如 Cocoen 和 TwentyTwenty。
为了防止出现“FLIC”,你可以使用某种过渡。几周前我看到过,但记不起是在哪个页面上看到的。尽管如此,我认为这可能是一个不错的解决方案——只要用户没有打开减少动画功能……
什么是“FLIC”?我在任何地方都找不到“FLIC”的含义..
嘿!
是否可以检测节能模式?
当我的 iPhone 处于节能模式时,有些视频无法加载。
在设备处于节能模式时添加一个 body 类会很有趣。
感谢你,这篇文章非常棒,它包含了我当前网站构建所需的一切。
有没有办法避免为媒体查询重复 CSS 代码:“prefers-color-scheme: dark”?
我也想知道这一点,Tomás。当你有一打属性的时候很乱,当你有一百个的时候简直是噩梦!一定有更好的方法……
纯 CSS: https://codepen.io/mori79/pen/ExwqNVv
相关帖子: https://stackoverflow.com/a/70811865/478018
你能写一篇关于 Brave 浏览器在我们开启强制黑暗模式时如何改变整个调色板的文章吗?
如何在黑暗模式下编辑表格?我试图让表格的边框颜色不同于黑色,但似乎无法获得我想要的结果。谢谢!
检查表格的边框是否在 HTML 本身中设置,然后在 CSS 中对其进行样式设置。
为什么 css-tricks 本身不尊重深色颜色偏好?这里有几篇文章介绍如何启用它,包括一些详细的文章,但截至目前,主要内容仍然是一个刺眼的白色矩形。
它离得也不远。在 @media 查询中大约有 8 行 CSS,它就可以正常工作。我现在用开发工具进行了一些调整,它运行得很好。用半透明的色调替换 .wp-block-column 背景,关闭几个重置,然后你就不需要做太多工作了。
好吧,现在你做到了。刚刚为网站创建了带开关的暗色主题,但我不知道 `prefers-color-scheme`
我也刚把黑暗模式浏览器插件换成了一个可以自定义颜色/CSS 的插件。
现在我可以为系统/浏览器黑暗模式设置我的配色方案。我可以让访问的每个网站都使用相同的配色方案,它碰巧与我在 Plasma 中的桌面主题没有太大区别。
统一。只需要偶尔关闭它,这样我才能看看现实世界是什么样子。