【FCon上海】与行业领袖共话AI大模型、数字化风控等前沿技术。 了解详情
写点什么

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

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

    阅读完需:约 30 分钟

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

AI 大模型超全落地场景&金融应用实践,8 月 16 - 19 日 FCon x AICon 大会联诀来袭、干货翻倍!


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

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

关注

评论

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

原生拖拽太拉跨了,纯JS自己手写一个拖拽效果,纵享丝滑

茶无味的一天

CSS html HTML5, CSS3 拖拉拽 原生js

js对象和原型、原型链的关系

hellocoder2029

JavaScript

Java | Map集合两种遍历方式

陌上

Java 编程 10月月更

5 why 分析法,一种用于归纳抽象出解决方案的好方法

程序员泥瓦匠

彻底搞懂nodejs事件循环

coder2028

node.js

Webpack配置实战

Geek_02d948

webpack

云安全系列2:访问安全和身份管理

HummerCloud

云计算 云安全 iam 身份和访问管理 10月月更

文读懂NodeJs知识体系和原理浅析

coder2028

node.js

SAP | 功能模块

暮春零贰

SAP 功能块 10月月更

嵌入式 Linux 入门 环境篇(二、安装虚拟机 — 体验 Ubuntu 22.04)

矜辰所致

Ubuntu20.04 嵌入式Linux 10月月更

webpack模块化的原理

Geek_02d948

webpack

webpack实战,手写loader和plugin

Geek_02d948

webpack

js进阶手写常见函数

hellocoder2029

JavaScript

漏洞评分高达9.8分!Text4Shell 会是下一个 Log4Shell吗?

SEAL安全

安全 log4j 漏洞分析 Log4j2 漏洞 软件供应链安全

实用的正则表达式知识【建议收藏】

何极光

正则表达式 10月月更 RegExp

js异步编程的三种模式

hellocoder2029

JavaScript

Java | HashMap和哈希表数据结构

陌上

Java 编程 10月月更

Java | Map集合的子类

陌上

Java 编程 10月月更

Apache Linkis 介绍

鹏哥AI数据

计算中间件 大数据 开源 数据计算 10月月更

SAP | 在ABAP中如何使用方法

暮春零贰

SAP 方法调用 10月月更

线上数据问题排查案例分享-因为 HMS 和底层 orc 文件中某字段的数据精度不一致造成的数据丢失问题

明哥的IT随笔

hadoop hive DataX

Workflow,要不要了解一下

华为云开发者联盟

人工智能 华为云 企业号十月 PK 榜

JavaScript模板字符串与es6中let的用法

何极光

ES6 let 模板字符串 10月月更

新闻贴 | KaiwuDB 受邀亮相中国 1024 程序员节

KaiwuDB

JavaScript刷LeetCode拿offer-二叉树层序遍历篇

Geek_07a724

JavaScript LeetCode

SAP | 子例程

暮春零贰

SAP 10月月更 子例程

Redis 知识点全面击破,多图警告

小小怪下士

Java redis 程序员

从 wepy 到 uniapp 变形记

vivo互联网技术

wepy uni-app 前端 编译器

0元上新丨PostgreSQL零基础开发指南+223页学习资料

博文视点Broadview

【文本检测与识别白皮书-3.2】第二节:场景文本识别方法

合合技术团队

人工智能 深度学习 文字识别 OCR 文本识别

深入nodejs的event-loop

coder2028

node.js

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