likes
comments
collection
share

工欲善其事必先利其器(css多主题)

作者站长头像
站长
· 阅读数 19

前言

多主题在 web 场景中是一种常见的提升用户体验的手段,本篇就简单介绍多主题相关的内容,作为 工欲善其事必先利其器(搭建组件库) 篇的一个补充

css多主题实现原理

css 多主题技术方案一直在演变中,从早期简单的样式覆盖到 CSS 变量,技术方案趋向解决工程化、规模化问题

css 样式覆盖

早期实现多主题方案一般是样式覆盖,也就通过选择器切换不同款式,这个很好理解,比如

body.light { background-color: #fff; }
body.dark { background-color: #cc0000; }

然后通过 DOM 操作改变 bodyclass 即可

这个方案的缺点也很明显

  • 需要需要同时书写多种主题样式,同时引入的 css 代码量较大且难以优化
  • 样式不好维护、拓展
  • 不易于管理
  • ...

多套 css 样式

这个方案就是编写多套 .css 主题样式文件,比如 light.cssdark.css,然后通过 link 引入,切换主题时就改变 link 标签的 href 属性

不过这个方案相对于上一个方案主要是解决了加载体积过大问题,其他问题依旧

CSS 变量

然后就是比较系统的解决方案 自定义属性(--*):CSS 变量 - CSS:层叠样式表 | MDN

定义根伪类 :root 的 CSS 变量

:root {
    --c-color: #666;
}

通过 var()使用


.text {  
  colorvar(--c-color)  
}

详细使用可参考使用 CSS 自定义属性(变量) - CSS:层叠样式表 | MDN

用作主题切换可参考如下写法

:root.light { --c-color:: #000; }
:root.dark { --c-color: #fff; }

.text {  
  colorvar(--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多主题 方面简单介绍了下,聪明的你一定能举一反三。

系列文章