DarkMode(2):深色模式解决方案
Date:
Dark Mode实现
现在可以利用
CSS 的媒体查询方法:prefers-color-scheme
方法还处于 W3C 草案规范:https://caniuse.com/?search=prefers-color-scheme
CSS 变量: CSS variables、CSS custom properties
CSS 变量除了 IE,其余各大浏览器都支持的比较好:https://caniuse.com/?search=variables
二者配合就可以实现页面主题跟随系统自动切换深浅模式 。
CSS 的媒体查询
prefers-color-scheme 是一种用于检测用户是否有将系统的主题色设置为亮色或者暗色的 CSS 媒体特性。 利用其设置不同主题模式下的 CSS 样式,浏览器会自动根据当前系统主题加载对应的 CSS 样式。light 适配浅色主题,dark 适配深色主题,no-preference 表示获取不到主题时的适配方案。
CSS
@media (prefers-color-scheme: light) { .article { background:#fff; color: #000; } } @media (prefers-color-scheme: dark) { .article { background:#000; color: white; } } @media (prefers-color-scheme: no-preference) { .article { background:#fff; color: #000; } }
Link 标签
<link href="./common.css" rel="stylesheet" type="text/css" /> <link href="./light-mode-theme.css" rel="stylesheet" type="text/css" /> <link href="./dark-mode-theme.css" rel="stylesheet" type="text/css" media="(prefers-color-scheme: dark)" />
一般推荐使用link标签解决
CSS 变量 + 媒体查询
window.matchMedia (https://developer.mozilla.org/zh-CN/docs/Web/API/Window/matchMedia) 方法可以用来查询 指定的媒体查询字符串解析后的结果。 结合 CSS 变量和 matchMedia 的查询结果,设置对应的 CSS 主题颜色。该方法更灵活,可以单独抽离主题色进行适配。
CSS 变量的作用域与 CSS 的"层叠"规则一致,优先级最高的声明生效。所以当 body 上存在 "dark" 类名时,:root .dark 会生效,否则 :root 生效。
.article { color: var(--text-color, #eee); background: var(--text-background, #fff); } :root { --text-color: #000; --text-background: #fff; } :root .dark { --text-color: #fff; --text-background: #000; }
使用 matchMedia 匹配主题媒体,深色模式匹配 (prefers-color-scheme: dark) ,浅色模式匹配 (prefers-color-scheme: light) 。
监听主题模式,深色模式时为 body 添加类名 dark,根据 CSS 变量的响应式布局特点,自动生效 dark 类名下的 CSS。
const darkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)'); // 判断是否匹配深色模式 if (darkMode && darkMode.matches) { document.body.classList.add('dark'); } // 监听主题切换事件 darkMode && darkMode.addEventListener('change', e => { if (e.matches) { document.body.classList.add('dark'); } else { document.body.classList.remove('dark'); } });
那么,针对不支持 CSS 变量的 IE 浏览器怎么办呢?不做兼容性处理的话那页面可能就是一团糟了。所以我们需要针对不兼容的浏览器做一些兜底处理,这里我们可以在 webpack 等构建工具中借助 post-css 的 postcss-css-variables (https://www.npmjs.com/package/postcss-css-variables) 插件来自动解析 CSS 变量对应的色值,并在原始 CSS 定义之上添加一条新的 CSS 样式,做到对不支持 CSS 变量浏览器的兼容。
// 根目录 postcss.config.js module.exports = { plugins: { "postcss-css-variables": { preserve: true, // 保留 var() 定义 preserveInjectedVariables: false, // 去除其他模块的重复变量 variables: require("./page.json"), // CSS 变量,可以支持多个 } } };
现在的 Web、App 项目大都引用第三方开源组件库,组件库一般会使用 Sass、Less 等 CSS 预处理器定义颜色变量作为组件的基础色值,并单独抽离为配置文件。所以,项目使用组件库时可以根据修改基础色值来自定义主题。那么针对项目的 深色模式适配方案也一样,主要分为三步:
组件库深浅色主题 适配
项目中 深浅色的 颜色适配
完成 CSS 变量到页面的注入
参考文章:
深色模式适配指南 https://www.zoo.team/article/dark-theme
转载本站文章《DarkMode(2):深色模式解决方案》,
请注明出处:https://www.zhoulujun.net/html/webfront/style/cssBase/2020_0914_8558.html