【css】前端换肤功能方案调研 & css变量换肤实践

it2025-03-21  15

场景:应用要做深浅两套主题,内嵌h5页面要根据用户当前选择的主题渲染对应的主题样式。 技术栈:vue-cli3 + less + Vant

接到需求后,上网调研了几种方案:切换className、切换css文件、使用预处理器(less/sass)变量、css变量等,最终选择的是css变量方案。

1. 利用class 命名空间

根据主题设置不同的类名,在类名下设置不同样式。

优点

实现简单,易理解兼容性好

缺点

易产生css优先级问题,造成代码混乱代码冗余不适用于用户自定义主题的场景

demo:codepen.io

2. 准备多套CSS主题

生成多套主题css文件,根据需要切换css文件href。

优点 易实现 缺点 代码冗余下载css需要额外时间,用户体验不佳

3. 使用 less modifyVars

antd主页 & antd pro使用的方案,实现优雅简单,与antd适配性好。原理上是使用 less 提供的 modifyVars 的方式进行覆盖变量,对 less-loader 的 options 属性进行相应配置。

// webpack.config.js module.exports = { rules: [{ test: /\.less$/, use: [{ loader: 'style-loader', }, { loader: 'css-loader', // translates CSS into CommonJS }, { loader: 'less-loader', // compiles Less to CSS + options: { + lessOptions: { // 如果使用less-loader@5,请移除 lessOptions 这一级直接配置选项。 + modifyVars: { + 'primary-color': '#1DA57A', + 'link-color': '#1DA57A', + 'border-radius-base': '2px', + }, + javascriptEnabled: true, + }, + }, }], // ...other rules }], // ...other config }

具体可以参考antd官网:https://ant.design/docs/react/customize-theme-cn

但是在实现的时候,发现这种方案并不能满足我的需求:

webpack无法异步配置,因此我不能异步获取用户主题后再加载less变量;(或许可以但我不知道?😅)less不支持动态修改变量。(但如果你使用的是antd,可以使用antd-theme-webpack-plugin 来异步修改。具体参考:Dynamic Theming in Browser using Ant Design )

4. css变量

利用css变量设置颜色,需要切换主题时,用js动态改变css变量的值。易理解易实现,兼容大部分浏览器(除了IE),并且支持动态换肤。

在根标签下声明变量 // global.less :root { --background-color: #000; --text-color: #fff; } 定义不同主题下的变量值 // theme.js module.exports = { DARK: { '--background-color': '#000', '--text-color': '#fff', }, LIGHT: { '--background-color': '#fff', '--text-color': '#000', }, } 在需要换肤的样式中使用变量(第二参数是默认值,为了兼容性考虑) // app.less #app { background: var(--background-color, #000); color: var(--text-color, #fff); } 根据需求场景更改css变量 // app.vue ... created() { .getTheme() .then(({theme}) => { if (appTheme === 'LIGHT') { Object.keys(THEME.DARK).forEach((key) => { document.documentElement.style.setProperty(key, THEME.LIGHT[key]) }) } }) },

done.

贴一个其他大佬写的动态换肤的demo:demo

ps: css变量写法兼容绝大部分场景,若要兼容IE需要使用css-vars-ponyfill降级。

参考:

[CSS] 自定义变量带你随心所欲,一键换肤CSS变量对JS交互组件开发带来的提升与变革一文总结前端换肤换主题基于Css Variable的主题切换完美解决方案
最新回复(0)