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 应用支持暗黑模式相关推荐

  1. 藏青色在html页面怎么写,Html页面支持暗黑模式的实现

    自19年开始,Android和IOS平台,都开始玩暗黑模式.当然这没什么不好,但是当我们的页面被用户在暗黑模式打开之后,会被那传统大白色瞬间闪瞎双眼. 下面会简单的说一下如何让页面支持暗黑模式. 准备 ...

  2. 安卓暗黑模式软件_优酷App ios版和Android 10版:支持暗黑模式使用[多图]

    暗黑模式是由ios 13系统走进大家的眼中的,在这之前,都没有暗黑模式这个手机使用模式,这个模式主要是为用户提供夜晚使用的最佳环境,在夜晚使用手机的时候也不会太伤害眼睛,之后安卓版本也出了这个版本,但 ...

  3. TOML-To-Go 更新,支持暗黑模式

    百度智能云 云生态狂欢季 热门云产品1折起>>>   GitHub: github.com/xuri/toml-to-go TOML 的目标是成为一个极简的配置文件格式.TOML 被 ...

  4. 苹果微信分身版ios_微信正式支持暗黑模式:iOS版已上线 安卓版随后就来

    微信暗黑模式一直受到网友的极大期待,今天(22日),微信 iOS版 终于迎来了 7.0.12 更新,正式加入对深色模式的支持. 微信 7.0.12 更新日志显示可跟随系统的设置,切换为深色模式. 从目 ...

  5. 一步到位:三行CSS代码轻松实现全网站暗黑模式

    本文首发于微信公众号:大迁世界, 我的微信:qq449245884,我会第一时间和你分享前端行业趋势,学习途径等等. 更多开源作品请看 GitHub https://github.com/qq4492 ...

  6. AmazeUI(妹子UI)中CSS组件、JS插件、Web组件的区别

    AmazeUI(妹子UI)是非常优秀的国产前端UI,现在来介绍一下AmazeUI中CSS组件.JS插件与Web组件的区别.  CSS组件顾名思义就是仅使用CSS渲染而成的组件,而JS插件也很容易理解, ...

  7. 6个很棒的PostCSS插件,让您成为一个CSS向导

    PostCSS是一个非常通用的工具,它可以通过javascript插件转换CSS样式.它的灵活性在于它的建造方式. PostCSS的核心部分是一个node.js模块,您可以使用NPM进行安装,它有一个 ...

  8. css中调整高度充满_6个很棒的PostCSS插件,让您成为一个CSS向导

    PostCSS是一个非常通用的工具,它可以通过javascript插件转换CSS样式.它的灵活性在于它的建造方式. PostCSS的核心部分是一个node.js模块,您可以使用NPM进行安装,它有一个 ...

  9. css 插件_10个很棒的PostCSS插件,使您成为CSS向导

    PostCSS是一种功能强大的工具,可以使用JavaScript插件转换CSS样式 . 它的灵活性在于其构建方式. PostCSS的核心部分是一个Node.js模块 ,您可以使用npm进行安装,它具有 ...

  10. 【Web技术】990- 前端站点一键支持暗色模式

    作者:冯伟尧 & 石嘉 & 刘大畅 需求 & 现状 作为近两年的「新时尚」,暗色/深色模式已经几乎成为了各家系统.应用以及 Web 站点的标配功能.想要支持暗色模式,本质是判断 ...

最新文章

  1. 十分钟用Windows服务器简单搭建DHCP中继代理!!
  2. 【采用】百度大规模知识图谱构建及智能应用
  3. 网摘--2014年5月12日
  4. 图像生成对抗生成网络gan_GAN生成汽车图像
  5. 【译】将IDataRecord自动填充到实体的扩展方法
  6. WPF:WPF显示PDF文档
  7. 第三周博客作业西北师范大学|李晓婷
  8. tracepro杂散光分析例子_光学系统杂散光分析(1)
  9. client mysql 逗号_Mysql-Client编码问题
  10. Web表单设计:点石成金的艺术(美)罗博乌斯基pdf
  11. 美图秀秀怎么去水印-美图秀秀怎么去水印图片教程
  12. vscode插件查找并导出到新电脑
  13. nofollow是什么意思,nofollow标签的作用是什么?
  14. 乱谈SOA——IT世界观及方法论
  15. 微信中提示浏览器打开网址链接如何解决
  16. 【英语:语法基础】C4.日常对话-餐饮专题
  17. 2020 C++ priority_queue 最大堆与最小堆介绍
  18. R语言笔记⑧——数据挖掘算法
  19. 计算机组成原理pc的长度,计算机组成原理课后习题答案(一到九章)
  20. python科学计算教程视频_【P14】Python科学计算与图形渲染库视频课程视频教程 it教程...

热门文章

  1. 《互联网大厂晋升指南》读书笔记-上
  2. PDF编辑器(widsmob pdfedit)v3.0.1
  3. 数码大师2013破解补丁|数码大师2013白金版注册破解补丁下载(附数码大师2013白金版注册码)
  4. 零基础如何自学编程?
  5. 基于安卓的宠物店预约商城APP源码
  6. HTML+CSS简单应用实例——购物网站的制作(一)
  7. android日记论文摘要,(毕业论文)基于android的日记本的设计与开发.doc
  8. 2023届计算机毕业设计源码
  9. 微信jssdk开发 java_Java微信公众平台开发(十一)--微信JSSDK中Config配置
  10. win10 android驱动安装失败,win10系统下小米手机驱动安装失败如何解决