写点什么

基于 Web 组件,手把手教你搭建黑暗主题

  • 2019-10-15
  • 本文字数:9288 字

    阅读完需:约 30 分钟

基于Web组件,手把手教你搭建黑暗主题


我们绕了一圈后,又回到了黑暗模式。从黑暗模式到浅色模式,绕了一大圈然后又回到了黑暗模式。在个人电脑时代的早期,黑暗模式是唯一的选择。单色 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


2019-10-15 15:282403
用户头像

发布了 61 篇内容, 共 27.8 次阅读, 收获喜欢 135 次。

关注

评论

发布
暂无评论
发现更多内容

01-回顾多线程

爱好编程进阶

Java 程序员 后端开发

[Day31-02]-[二叉树]二叉搜索树节点最小距离

方勇(gopher)

LeetCode 数据结构和算法

15-spring整合mybatis方式一

爱好编程进阶

Java 程序员 后端开发

18 应用服务器集群的伸缩性设计

爱好编程进阶

Java 程序员 后端开发

2021年最新调查:86% 的 Java 开发人员 依赖 Spring 框架

爱好编程进阶

Java 程序员 后端开发

3分钟带你彻底搞懂 Kafka

爱好编程进阶

程序员 后端开发

9 个 Java 性能调优技巧,YYDS!

爱好编程进阶

Java 程序员 后端开发

渗透实战之内网渗透流程

网络安全学海

网络安全 信息安全 渗透测试 WEB安全 漏洞挖掘

千万级学生管理系统考试存储系统方案

踩着太阳看日出

架构训练营

架构实战营 第 6 期 模块四课后作业

火钳刘明

#架构实战营 「架构实战营」

模块四:作业

本人法海

「架构实战营」

3 面蚂蚁,一路过关斩将 成功拿到 offer 定级 P6,大厂面试雀食有点难

爱好编程进阶

Java 程序员 后端开发

一份送给IT工程师们的礼物,观测云2022正式发布!

观测云

分布式系统学习资料汇总

Geek_4zc1nt

分布式 分布式系统 资料 资料整理 公开课

天下谁人不识君:当IPv6+成为千行百业的朋友

脑极体

[Day30]-[二叉树]第二小的值

方勇(gopher)

LeetCode 数据结构和算法

ffmpeg命令参数类型

Loken

Java面试通关秘籍:笔记导图+面试文档+视频讲解

Java架构追梦

Java 程序员 后端开发

Fedora 上如何安装 gitea

HoneyMoose

倒计时0日!Apache DolphineScheduler4月 Meetup 大佬手把手教你大数据开发,离线调度

白鲸开源

5 年 Java 经验,字节、美团

爱好编程进阶

Java 程序员 后端开发

Go 语言入门很简单:Go 计时器

宇宙之一粟

Go 语言 计时器 4月月更

2020年最全Java面试汇总整理(含答案)

爱好编程进阶

Java 程序员 后端开发

2021阿里总监最新整理:初级-中级-高级大厂面试真题(附答案解析

爱好编程进阶

Java 程序员 后端开发

未来计算图鉴:十年后的计算长什么模样?

脑极体

[Day31-01]-[二叉树]二叉树的直径

方勇(gopher)

LeetCode 数据结构和算法

【ELT.ZIP】OpenHarmony啃论文俱乐部——点燃主缓存压缩技术火花

ELT.ZIP

gpu OpenHarmony ELT.ZIP 主缓存

一个普通App变成Launcher的故事

Changing Lin

android Launcher

2020,微服务降温了?

爱好编程进阶

Java 程序员 后端开发

20多年的岁月里一路走来满是辜负与遗憾,从双非到阿里SP,收到offer的那天我哭惨了

爱好编程进阶

Java 程序员 后端开发

Postman 如何删除一个工作空间

HoneyMoose

基于Web组件,手把手教你搭建黑暗主题_语言 & 开发_Indrek Lasn_InfoQ精选文章