我们绕了一圈后,又回到了黑暗模式。从黑暗模式到浅色模式,绕了一大圈然后又回到了黑暗模式。在个人电脑时代的早期,黑暗模式是唯一的选择。单色 CRT 计算机显示器的工作原理是将电子束发射到荧光屏上。早期 CRT 中使用的荧光粉是绿色的,导致文本显示为绿色,而屏幕的其余部分显示为黑色。这些模式通常被称为绿色屏幕。
图片来自 wikimedia
随着后来彩色 CRT 的引入,显示器通过使用红、绿、蓝三色荧光粉可以显示多种颜色。白色是通过同时激活所有三种荧光粉而产生的。现在我们又回到了黑暗主题,因为它让人的眼睛更舒服,并且从主观审美上让人更愉悦。
我非常喜欢 web 组件,它们让 web 开发变成了面向组件开发的方式,我很喜欢这种方式。下面就让我们仅使用 web 组件构建一个切换黑暗和浅色主题的小程序。
“面向组件的编程将是未来的趋势。"——Indrek Lasn
Web 组件是许多不同技术的组合,它允许您创建可重用的自定义元素(其封装的功能可与您的其他代码隔离开来),并在 web 应用程序中使用这些元素。如果您不太了解 web 组件是什么,请查看“Web组件的概要”。
开始
我们只需要一个 web 浏览器和一个文本编辑器就够了。然后创建 index.html 文件。如果您正在使用emmet,您可以直接输入!,然后点击 tab 键。这将为您显示出 index.html 的样例代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Toggle</title>
</head>
<body>
</body>
</html>
复制代码
元素
多亏了开源代码,我们已经有了一个方便的组件来满足我们的需求。它被称为dark-mode-toggle——我们可以通过 CDN 包含该组件,或者将之视为 NPM 软件包安装。
以下组件是一个自定义元素,使您可以轻松地将一个黑暗模式切换开关放在您的网站上,您一开始可以使用prefers-color-scheme读取用户设置的偏好,但也允许用户选择性地只在这个网页上覆盖系统设置,并且这种单独设置可以是永久生效的。
被称为prefers-color-scheme的媒体特性用于检测用户的页面请求所要求的是浅色主题还是黑暗主题。它有以下三个值。
no-preference:表示用户没有向浏览器显示任何首选项。此关键字值在布尔上下文中计算为 false。
light:表示用户已经告知浏览器,他们更喜欢浅色主题的页面(浅色背景上的深色文本)。
dark:表示用户已经告知浏览器,他们更喜欢黑暗主题的页面(深色背景上的浅色文本)。
将以下代码放到 index.html 的部分:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="common.css" />
<link
rel="stylesheet"
href="light.css"
media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)"
/>
<link
rel="stylesheet"
href="dark.css"
media="(prefers-color-scheme: dark)"
/>
<script
type="module"
src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"
></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Toggle</title>
</head>
<body>
</body>
</html>
复制代码
自定义元素假设您已经将 CSS 组织到不同的文件中,浏览器会根据样式表相应的 link 元素中的 media 属性有条件地加载这些文件。以下样式表被命名为 common.css、light.css 和 dark.css——注意每个主题是怎样具有自己的封装样式的。继续创建这三个样式表。
touch common.css light.css dark.css
复制代码
这是一个很好的高性能模式,因为浏览器会遵循人们当前的主题偏好,而不会强制人们下载他们不需要的 CSS,虽然不匹配的样式表仍然会被加载,但是不会在关键的渲染通道上争夺带宽资源。
接下来,将元素添加到 index.html 中。
<aside>
<dark-mode-toggle
id="dark-mode-toggle"
legend="Theme Switcher"
light="Light"
dark="Dark"
appearance="switch"
permanent="false"
></dark-mode-toggle>
</aside>
复制代码
添加 dark-mode-toggle 元素
到了这一步,我们还应该添加一些内容。毕竟,我们想要看到并测试我们的结果。下面是我们现在的 index.html 文件的样子:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="common.css" />
<link
rel="stylesheet"
href="light.css"
media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)"
/>
<link
rel="stylesheet"
href="dark.css"
media="(prefers-color-scheme: dark)"
/>
<script
type="module"
src="https://googlechromelabs.github.io/dark-mode-toggle/src/dark-mode-toggle.mjs"
></script>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Toggle</title>
</head>
<body>
<aside>
<dark-mode-toggle
id="dark-mode-toggle"
legend="Theme Switcher"
light="Light"
dark="Dark"
appearance="switch"
permanent="false"
></dark-mode-toggle>
</aside>
<main>
<h1>Hi there!</h1>
<p>
Lorem ipsum dolor sit amet, legere ancillae ne vis. Ne vim laudem
accusam consectetuer, eu utinam integre abhorreant sea. Quo eius veri
ei.
</p>
<form id="content">
<fieldset>
<legend>Lorem ipsum</legend>
<div>
<select>
<option>Lorem</option>
<option>Ipsum</option>
</select>
</div>
<div>
<button type="button">Lorem</button>
</div>
<div>
<input type="text" value="Lorem ipsum" />
</div>
<div>
<input type="search" value="Lorem ipsum" />
</div>
<div>
<label><input checked type="checkbox" /> Lorem</label>
<label><input type="checkbox" /> Ipsum</label>
</div>
<div>
<label><input checked name="foo" type="radio" /> Lorem</label>
<label><input name="foo" type="radio" /> Ipsum</label>
</div>
</fieldset>
</form>
</main>
</body>
</html>
复制代码
最后,我们需要声明黑暗和浅色主题的样式。请从下面的代码片段中获取样式。
common.css
这些样式在黑暗和浅色主题之间可以复用。
:root {
color-scheme: dark light; /* stylelint-disable-line property-no-unknown */
--heading-color: red;
--duration: 0.5s;
--timing: ease;
}
*,
::before,
::after {
box-sizing: border-box;
}
body {
margin: 0;
transition: color var(--duration) var(--timing),
background-color var(--duration) var(--timing);
font-family: sans-serif;
font-size: 12pt;
background-color: var(--background-color);
color: var(--text-color);
display: flex;
justify-content: center;
}
main {
margin: 1rem;
max-width: 30rem;
position: relative;
}
h1 {
color: var(--heading-color);
text-shadow: 0.1rem 0.1rem 0.1rem var(--shadow-color);
transition: text-shadow var(--duration) var(--timing);
}
img {
max-width: 100%;
height: auto;
transition: filter var(--duration) var(--timing);
}
p {
line-height: 1.5;
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto;
}
fieldset {
border: solid 0.1rem;
box-shadow: 0.1rem 0.1rem 0.1rem var(--shadow-color);
transition: box-shadow var(--duration) var(--timing);
}
div {
padding: 0.5rem;
}
aside {
position: absolute;
right: 0;
padding: 0.5rem;
}
aside:nth-of-type(1) {
top: 0;
}
aside:nth-of-type(2) {
top: 3rem;
}
aside:nth-of-type(3) {
top: 7rem;
}
aside:nth-of-type(4) {
top: 12rem;
}
#content select,
#content button,
#content input[type="text"],
#content input[type="search"] {
width: 15rem;
}
dark-mode-toggle {
--dark-mode-toggle-remember-font: 0.75rem "Helvetica";
--dark-mode-toggle-legend-font: bold 0.85rem "Helvetica";
--dark-mode-toggle-label-font: 0.85rem "Helvetica";
--dark-mode-toggle-color: var(--text-color);
--dark-mode-toggle-background-color: none;
margin-bottom: 1.5rem;
}
#dark-mode-toggle {
--dark-mode-toggle-dark-icon: url("moon.png");
--dark-mode-toggle-light-icon: url("sun.png");
--dark-mode-toggle-icon-size: 1rem;
--dark-mode-toggle-icon-filter: invert(100%);
}
复制代码
注意 color-scheme 属性。color-scheme 属性仍在开发中,可能还没有得到完全支持。Chrome 将在 2019 年底对其提供全面支持。
dark.css
这些是我们黑暗主题的样式。
:root {
--background-color: rgb(40, 44, 53);
--text-color: rgb(240, 240, 240);
}
.icon {
filter: invert(100%);
}
/* 如果不存在黑暗模式用户agent,那就模拟它 */
select,
input,
button,
option {
color: var(--text-color);
background-color: var(--background-color);
border-width: 1px;
border-radius: 1px;
}
/* Else, use the user agent stylesheet */
@media (prefers-color-scheme: dark) {
select,
input,
button,
option {
color: unset;
background-color: unset;
}
}
复制代码
dark.css
light.css
最后是浅色主题的样式。
:root {
--background-color: rgb(240, 240, 240);
--text-color: rgb(15, 15, 15);
}
复制代码
在浏览器中打开 index.html 文件。您可以在本地打开它,也可以启动一个现成的 HTTP 服务器。在我的例子中,我将使用内置的 Python 服务器来打开它。
$ python -m SimpleHTTPServer
复制代码
启动我们的 Python 服务器
现在,如果我们打开浏览器并输入 localhost:8000——我们应该会看到以下内容:
继续点击右上角的主题切换按钮。
太酷了!这招很管用。您可以在GitHub代码库中找到所有的图片资源。
如果您是 JavaScript 新手,而且想要学习这门语言,我建议您从阅读书籍开始,边学边构建代码。从“学习JavaScript的更聪明方法”这本书开始,这里有一个有趣的应用程序列表。
谢谢您的阅读,我希望您学到了一些东西。继续加油!
原文链接:
How to Build Light and Dark Themes With Web Components
评论