阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

基于 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:281907
用户头像

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

关注

评论

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

人类 vs AI:玩梗大作战,看看谁是最后的赢家?

LigaAI

测评 ChatGPT 文心一言 GPT-4 企业号 4 月 PK 榜

一文理清 TiDB 与 MySQL 中的常用字符集及排序规则

TiDB 社区干货传送门

新版本/特性解读 6.x 实践

政务智能办体验升级、乳腺癌创新药加速研发,飞桨和文心大模型驱动应用智能涌现

飞桨PaddlePaddle

百度飞桨

【4.21-4.28】写作社区优秀技术博文一览

InfoQ写作社区官方

热门活动 优质创作周报

赋能产业新发展,华秋电子携多高层板积极参与成都工博会

华秋电子

聊聊智能语音交互系统

轻口味

AI 三周年连更

说一个大家都知道的 Spring Boot 小细节!

江南一点雨

Java springboot

汽车电阻:新能源时代来临,车用电阻市场机遇正在显现

华秋电子

牛皮!GitHub上标星90.6K的Java面试指南+笔记

Java你猿哥

Java 程序员 面试 ssm java核心知识点

阿里大佬纯手写Angular和Spring Boot全栈技能修炼手册

做梦都在改BUG

Java Spring Boot angular 全栈

我用Bitmap实现亿级数据统计

Java你猿哥

Java redis 架构 ssm BitMap

TiDB x Flink x Iceberg 实时 ODS 实践

TiDB 社区干货传送门

TiDB x Flink 数据集成实践

TiDB 社区干货传送门

TiSpark v3.0.3 & v3.1.3 发布

TiDB 社区干货传送门

新版本/特性解读

深度学习模型可视化-keras版

AIWeker

Python 深度学习 可视化 keras 三周年连更

eBPF的发展演进---从石器时代到成为神(五)

统信软件

操作系统 Linux Kenel

Spring Boot扩展:深入分析 IoC 容器

Java你猿哥

Java spring ssm 架构师 spring ioc

Java面试很难?啃完阿里老哥这套Java架构速成笔记,我都能拿30K

Java你猿哥

Java 架构 面试 分布式 java基础

IM开发干货分享:IM客户端不同版本兼容运行的技术思路和实践总结

JackJiang

网络编程 即时通讯 即时通讯IM

叹服!华为高工手写344页高性能Java架构核心原理实战大神手册

做梦都在改BUG

Java 架构 高并发

软硬件负载均衡 IP 地址透传

TiDB 社区干货传送门

数据库架构设计 数据库连接

中移链控制台对接4A平台功能验证介绍

BSN研习社

华秋干货铺 | PCB阻抗计算的可制造性设计

华秋电子

IntelliJ IDEA太重量级了?不妨尝试一下新的IDE工具

Java你猿哥

Java emacs ssm IDEA IntelliJ IDEA

大白话讲解synchronized锁升级套路

做梦都在改BUG

Alibaba内部首发“M8级”500页微服务架构手册,GitHub上杀疯了

Java你猿哥

Java 架构 微服务 ssm 架构师

手把手教你成为 TiDB 的 Contributor

TiDB 社区干货传送门

实践案例 故障排查/诊断 TiDB 源码解读

看完这篇推特视频怎么下载到手机相册的教程,我又可以了!

frank

twitter

太阳能是否能助力LED显示屏节能?

Dylan

节能 LED显示屏 太阳能

你真的理解 Golang 切片吗?全切片表达式及切片使用技巧

宇宙之一粟

Go 切片 三周年连更

boot-admin整合Quartz实现动态管理定时任务

Java你猿哥

Java 架构 ssm vue admin springboot整合quartz

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