CSS | 使用 PostCSS 插件让 Web 应用支持暗黑模式
1 概述
通过使用 CSS 变量,可以实现暗黑模式。比如使用媒体查询器:
:root {color-scheme: light dark;background: white;color: black;
}@media (prefers-color-scheme: dark) {:root {background: black;color: white;}
}
如果有很多颜色需要处理,此时就要用到 CSS 变量。
:root {color-scheme: light dark;--nav-bg-color: #F7F7F7;--content-bg-color: #FFFFFF;--font-color: rgba(0,0,0,.9);
}@media (prefers-color-scheme: dark) {:root {--nav-bg-color: #2F2F2F;--content-bg-color: #2C2C2C;--font-color: rgba(255, 255, 255, .8);}
}:root {color: var(--font-color)
}.header {background-color: var(--nav-bg-color);
}.content {background-color: var(--content-bg-color);
}
可以看到这种办法代码简单易懂,问题是var
关键字不兼容 IE 浏览器。
还有一个办法,就是使用 less.js
实时编译 CSS
代码,比如:
<script src="less.js"></script>
<script>
less.modifyVars({ '@text-color': '#fff', '@bg-color': '#000' });
</script>... var less = require("less");
var fs = require("fs");fs.readFile("./index.less", "utf-8", (err, str) => {less.render(str,{paths: [".", "./components"], // 搜寻由 @import 指向的目录compress: true, modifyVars: {"@text-color": "#fff","@bg-color": "#000",},},function (e, output) {console.log(output.css);});
});
使用 less 的缺点是,当点击切换按钮时,会导致卡顿。
当然,也可以通过DOM
动态更新 CSS
代码。
function changeTheme(theme) {const styleCss = document.querySelector("#styleCss");if (styleCss) {styleCss.href = `/assets/css/${theme}.css`;} else {const head = document.getElementsByTagName("head")[0];const link = document.createElement("link");link.id = "styleCss";link.type = "text/css";link.rel = "stylesheet";link.dataset.type = "theme";link.href = `/assets/css/${theme}.css`;head.appendChild(link); }localStorage.setItem("theme", theme);
}
使用 DOM 动态更改的办法,需要把颜色单独作成样式文件,导致配置繁琐。
2 什么是 PostCSS ?
PostCSS
核心包含一个生成 CSS
抽象语法树的AST
解析器,能将 CSS
代码抽象成一个节点树。如果代码发生更改,节点树也会更新。
核心过程是 解析 => 转换 => 生成,类似 Babel
。形式如下图所示:
3 举个例子
比如下面的 .less
代码:
我们要将其转换为:
Wepack 的配置如下:
module: {rules:[//...{test: /\.less$/i,use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'],},//...]
}
3.1 编写 PostCSS 插件
我们可以使用 postcss-plugin-boilerplate
脚手架,这个脚手架可以创建一个 postcss-plugin
,并且还可以配置jest
单元测试。流程图如下:
当然,也可以在项目根目录下手动创建一个 PostCSS
插件。
// test-plugin.js
var postcss = require("postcss");module.exports = postcss.plugin("pluginname", function (opts) {opts = opts || {}; // plugin 参数return function (root, result) {// Transform the CSS AST};
});
然后,将其放入 postcss.config.js
配置文件中。
module.exports = {plugins: [require('./test-plugin'),require('autoprefixer')]
};
编写代码,完成插件功能。
var postcss = require("postcss");module.exports = postcss.plugin("postcss-backwards", function (opts) {opts = opts || {};return function (root, result) {// Iterate over all style nodesroot.walkDecls((declaration) => {declaration.value = declaration.value.split("").reverse().join("");});};
});
这是一个没有实际意义的插件,仅作教学使用。
3.2 如何使用 PostCSS 实现暗黑模式支持 ?
将less
文件导入项目。
import "./default-theme.less";
import "./dark-theme.less";
component.less
.box{width: 100px;height: 100px;border: 1px solid @border;background-color: @bg;color: @color;
}
default-theme.less
@import "./component";@border: #333;
@color: #000;
@bg: #fff;
dark-theme.less
@import "./component";@border: #999;
@color: #fff;
@bg: #000;
转换模块
function isEmpty(arr) {return Array.isArray(arr) && arr.length === 0;
}const hasColorProp = (colorProps, declProp) =>colorProps.some((prop) => declProp.includes(prop));module.exports = (opts = {}) => {if (!opts.colorProps) {opts.colorProps = ["color", "background", "border", "box-shadow", "stroke"];}return (root) => {let theme;const file = root.source.input.file || "";const matched = file.match(/(?<theme>[a-zA-Z0-9]+)-theme.(less|css|scss|sass)/);if (matched && matched.groups.theme !== "default") {theme = matched.groups.theme;} else {if (process.env.NODE_ENV == "test") {theme = "test";}}if (theme) {root.walkRules((rule) => {rule.walkDecls((decl) => {if (!hasColorProp(opts.colorProps, decl.prop)) {decl.remove();}});if (isEmpty(rule.nodes)) {rule.remove();} else {rule.selector = rule.selector.replace(/\n/g, "").split(",").map((s) => `.${theme} ${s}`).join(",\n");}});}};
};
4 实施步骤
4.1 通过文件名来确定是否需要生成皮肤样式
const file = root.source.input.file || "";const matched = file.match(/(?<theme>[a-zA-Z0-9]+)-theme.(less|css|scss|sass)/
);
4.2 删除不包含颜色的样式
只保留边框颜色、背景颜色和包含颜色的 CSS 属性。并且,删除不包含 CSS 属性的选择器。
["color", "background","border","box-shadow","stroke",]
4.3 配置规则
module.exports = [{prop: ["background-color", "background"],from: ["#fff", "#ffffff", "@white"],to: "@component-background",},{prop: ["border", "border-color"],from: ["#D3D9E4", "#D3D9E2"],to: "@border-color",},{prop: ["color"],from: ["#666E79", "#5C6268"],to: "@text-color",}
];
4.4 执行转化
const syntax = require("postcss-less");
var fs = require("fs");
const path = require("path");
const rules = require("./rule.js");var glob = require("glob");function log(file, node, to) {console.log("\x1b[32m",`convert ${file} ${node.source.start.line}:${node.source.start.column} ${node.parent.selector} ${node.prop} from ${node.value} to ${to}`);
}let codes = {};// options is optional
glob("./src/**/*.less", function (er, files) { files.forEach((file) => {var ast = syntax.parse(file);// traverse AST and modify itast.walkDecls(function (node) {rules.forEach((item) => {if (item.prop.includes(node.prop) && item.from.includes(node.value)) {node.value = item.to;log(file, node, item.to);}});});fs.writeFileSync(path.resolve(file), syntax.nodeToString(ast));});
});
CSS | 使用 PostCSS 插件让 Web 应用支持暗黑模式相关推荐
- 藏青色在html页面怎么写,Html页面支持暗黑模式的实现
自19年开始,Android和IOS平台,都开始玩暗黑模式.当然这没什么不好,但是当我们的页面被用户在暗黑模式打开之后,会被那传统大白色瞬间闪瞎双眼. 下面会简单的说一下如何让页面支持暗黑模式. 准备 ...
- 安卓暗黑模式软件_优酷App ios版和Android 10版:支持暗黑模式使用[多图]
暗黑模式是由ios 13系统走进大家的眼中的,在这之前,都没有暗黑模式这个手机使用模式,这个模式主要是为用户提供夜晚使用的最佳环境,在夜晚使用手机的时候也不会太伤害眼睛,之后安卓版本也出了这个版本,但 ...
- TOML-To-Go 更新,支持暗黑模式
百度智能云 云生态狂欢季 热门云产品1折起>>> GitHub: github.com/xuri/toml-to-go TOML 的目标是成为一个极简的配置文件格式.TOML 被 ...
- 苹果微信分身版ios_微信正式支持暗黑模式:iOS版已上线 安卓版随后就来
微信暗黑模式一直受到网友的极大期待,今天(22日),微信 iOS版 终于迎来了 7.0.12 更新,正式加入对深色模式的支持. 微信 7.0.12 更新日志显示可跟随系统的设置,切换为深色模式. 从目 ...
- 一步到位:三行CSS代码轻松实现全网站暗黑模式
本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一时间和你分享前端行业趋势,学习途径等等. 更多开源作品请看 GitHub https://github.com/qq4492 ...
- AmazeUI(妹子UI)中CSS组件、JS插件、Web组件的区别
AmazeUI(妹子UI)是非常优秀的国产前端UI,现在来介绍一下AmazeUI中CSS组件.JS插件与Web组件的区别. CSS组件顾名思义就是仅使用CSS渲染而成的组件,而JS插件也很容易理解, ...
- 6个很棒的PostCSS插件,让您成为一个CSS向导
PostCSS是一个非常通用的工具,它可以通过javascript插件转换CSS样式.它的灵活性在于它的建造方式. PostCSS的核心部分是一个node.js模块,您可以使用NPM进行安装,它有一个 ...
- css中调整高度充满_6个很棒的PostCSS插件,让您成为一个CSS向导
PostCSS是一个非常通用的工具,它可以通过javascript插件转换CSS样式.它的灵活性在于它的建造方式. PostCSS的核心部分是一个node.js模块,您可以使用NPM进行安装,它有一个 ...
- css 插件_10个很棒的PostCSS插件,使您成为CSS向导
PostCSS是一种功能强大的工具,可以使用JavaScript插件转换CSS样式 . 它的灵活性在于其构建方式. PostCSS的核心部分是一个Node.js模块 ,您可以使用npm进行安装,它具有 ...
- 【Web技术】990- 前端站点一键支持暗色模式
作者:冯伟尧 & 石嘉 & 刘大畅 需求 & 现状 作为近两年的「新时尚」,暗色/深色模式已经几乎成为了各家系统.应用以及 Web 站点的标配功能.想要支持暗色模式,本质是判断 ...
最新文章
- 十分钟用Windows服务器简单搭建DHCP中继代理!!
- 【采用】百度大规模知识图谱构建及智能应用
- 网摘--2014年5月12日
- 图像生成对抗生成网络gan_GAN生成汽车图像
- 【译】将IDataRecord自动填充到实体的扩展方法
- WPF:WPF显示PDF文档
- 第三周博客作业西北师范大学|李晓婷
- tracepro杂散光分析例子_光学系统杂散光分析(1)
- client mysql 逗号_Mysql-Client编码问题
- Web表单设计:点石成金的艺术(美)罗博乌斯基pdf
- 美图秀秀怎么去水印-美图秀秀怎么去水印图片教程
- vscode插件查找并导出到新电脑
- nofollow是什么意思,nofollow标签的作用是什么?
- 乱谈SOA——IT世界观及方法论
- 微信中提示浏览器打开网址链接如何解决
- 【英语:语法基础】C4.日常对话-餐饮专题
- 2020 C++ priority_queue 最大堆与最小堆介绍
- R语言笔记⑧——数据挖掘算法
- 计算机组成原理pc的长度,计算机组成原理课后习题答案(一到九章)
- python科学计算教程视频_【P14】Python科学计算与图形渲染库视频课程视频教程 it教程...
热门文章
- 《互联网大厂晋升指南》读书笔记-上
- PDF编辑器(widsmob pdfedit)v3.0.1
- 数码大师2013破解补丁|数码大师2013白金版注册破解补丁下载(附数码大师2013白金版注册码)
- 零基础如何自学编程?
- 基于安卓的宠物店预约商城APP源码
- HTML+CSS简单应用实例——购物网站的制作(一)
- android日记论文摘要,(毕业论文)基于android的日记本的设计与开发.doc
- 2023届计算机毕业设计源码
- 微信jssdk开发 java_Java微信公众平台开发(十一)--微信JSSDK中Config配置
- win10 android驱动安装失败,win10系统下小米手机驱动安装失败如何解决