工欲善其事必先利其器(css多主题)
前言
多主题在 web 场景中是一种常见的提升用户体验的手段,本篇就简单介绍多主题相关的内容,作为 工欲善其事必先利其器(搭建组件库) 篇的一个补充
css多主题实现原理
css 多主题技术方案一直在演变中,从早期简单的样式覆盖到 CSS 变量,技术方案趋向解决工程化、规模化问题
css 样式覆盖
早期实现多主题方案一般是样式覆盖,也就通过选择器切换不同款式,这个很好理解,比如
body.light { background-color: #fff; }
body.dark { background-color: #cc0000; }
然后通过 DOM 操作改变 body
的 class
即可
这个方案的缺点也很明显
- 需要需要同时书写多种主题样式,同时引入的 css 代码量较大且难以优化
- 样式不好维护、拓展
- 不易于管理
- ...
多套 css 样式
这个方案就是编写多套 .css
主题样式文件,比如 light.css
、dark.css
,然后通过 link
引入,切换主题时就改变 link
标签的 href
属性
不过这个方案相对于上一个方案主要是解决了加载体积过大问题,其他问题依旧
CSS 变量
然后就是比较系统的解决方案 自定义属性(--*):CSS 变量 - CSS:层叠样式表 | MDN
定义根伪类 :root
的 CSS 变量
:root {
--c-color: #666;
}
通过 var()使用
.text {
color: var(--c-color)
}
详细使用可参考使用 CSS 自定义属性(变量) - CSS:层叠样式表 | MDN
用作主题切换可参考如下写法
:root.light { --c-color:: #000; }
:root.dark { --c-color: #fff; }
.text {
color: var(--c-color)
}
切换主题时只需切换 HTML 的 class 即可
以上示例只需要维护基本的 CSS 变量即可,这可极大的降低了管理、维护和拓展成本
毫无疑问, CSS 变量 方案能用则用,在现代工程化体系中不考虑兼容性问题的话,这是成本最低的方案了
css 预处理语言方案
现代前端项目估计很少直接使用 css,一般都是使用预处理语言: less、sass、stylus等
以 less
为例,一般可以在打包工具中进行以下类似的配置就可以很定制主题
lessOptions: {
modifyVars: { '@primary-color': '#1DA57A' },
javascriptEnabled: true
}
而想要在线切换主题就需要把 less
编译工具打包到线上,切换主题的时候把对应主题色传入 less
编译器进行编译得到 css
样式,然后替换原有 <style/>
标签内容
相关案例
antd-theme-webpack-plugin
antd-theme-webpack-plugin 这个库是基于 webpack
来的,如果使用的是 vite
则无法使用, vite
在开发环境使用 esbuild
,生产环境使用的是 roallup
来进行打包
这里就不演示插件使用和打包后的结果了,相信大家跟着文档操作很容易得到结果
从结果上说,这个插件在切换主题时需要运行时编译 less
,也就是说比较耗时的,也可以考虑使用 webpack-theme-color-replacer 库来处理
antd-theme-generator
antd-theme-generator 这个库把 less
提升到了运行阶段,我们代码一般会进行打包压缩等,使用这个库着需要配置 less
相关的静态资源不能被打包
全局污染
以上实现基本都是基于全局实现,对于一些场景一些应用可能需要局部控制,这又牵扯到工程化改造,还是相当头痛的
以 Ant Design
组件库为例,提供了 ConfigProvider
方式算是比较合理的方案了
不同项目要求不一样,并没有十全十美的解决方案,不过了解了技术原理的你应该可以根据项目需要定制自己解决方案,这里就不详细介绍了
总结
css
作为前端非常重要的一部分,说简单也可以很简单要说难也可以非常难,以前写项目的时候毫不夸张的说 css 和 js 的耗时可以对半分甚至更多,现代工程化有一部分内容也是在解决或者说减少 css
编码时间,通过ui
规范、工程化管理、组件化等都在一定程度上解决 css
管理问题,本篇仅从 css多主题 方面简单介绍了下,聪明的你一定能举一反三。
系列文章
转载自:https://juejin.cn/post/7244352006814367804