导引
最近工作需要,需要对项目做主题色的切换; 分享下主题色切换遇到问题,以及解决的思路;
项目实际
vue3项目,安装的依赖有element-plus,切换主题色,项目中使用的element-plus组件变为当前的主题色;
element-plus 主题色切换
element-plus 官网完档中,对切换主题色做了介绍,有以下几种方案:
- 1、修改scss变量
packages/theme-chalk/src/common/var.scss文件中查找scss变量修改- 新建一个样式文件,例如
styles/element/index.scssscss代码解读复制代码// styles/element/index.scss /* 只需要重写你需要的即可 */ @forward "element-plus/theme-chalk/src/common/var.scss" with ( $colors: ( "primary": ( "base": green, ), ), ); - 然后在你的项目入口文件中,导入这个样式文件替换 Element Plus 内置的 CSS
- 2、修改css变量
scss代码解读复制代码```scss :root { --el-color-primary: green; } ``` ```js const el = document.documentElement // const el = document.getElementById(''xxx'') // get css var getComputedStyle(el).getPropertyValue(`--el-color-primary`) // set css var el.style[''--el-color-primary''] = ''red'' ```
- 3、更新scss变量
css代码解读复制代码```scss /* 主题颜色 */ $--color-primary: teal; /* icon font 路径, 必须提供 */ $--font-path: ''~element-plus/lib/theme-chalk/fonts''; @use ''~element-plus/packages/theme-chalk/src/index''; ```
- 4、cli主题生成使用cli先生成一个.scss,修改变量值,再生成对应.css文件
- 安装 element-theme
- 安装 element-theme-chalk
- et -i [自定义输出文件]
- 编辑生成的scss文件
- et
- ccs文件 默认生成在theme/文件夹中
开始实践
思路1:修改css变量
-
采用方法:方案2,修改css变量,这种方法最直观,且是动态的、颜色不限制;
-
思路:
js代码解读复制代码const color = #121212 const el = document.documentElement console.log(getComputedStyle(el).getPropertyValue(`--el-color-primary`)) el.style.setProperty("--el-color-primary", color); -
问题:部分组件:el-button、el-tag等主题色不会发生变化,因为组件的主题色,不受css全局变量控制,而是组件中的css变量--el-button-background-color控制;
css代码解读复制代码.el-button--primary { --el-button-font-color: #ffffff; --el-button-background-color: #409eff; --el-button-border-color: #409eff; --el-button-hover-color: #66b1ff; --el-button-active-font-color: #e6e6e6; --el-button-active-background-color: #0d84ff; --el-button-active-border-color: #0d84ff; } .el-button { --el-button-font-weight: var(--el-font-weight-primary); --el-button-border-color: var(--el-border-color-base); --el-button-background-color: var(--el-color-white); --el-button-font-color: var(--el-text-color-regular); background: var(--el-button-background-color, var(--el-color-white)); border: var(--el-border-base); border-color: var(--el-button-border-color, var(--el-border-color-base)); color: var(--el-button-font-color, var(--el-text-color-regular)); ... } -
解决:除了修改css全局变量,同时也要修改组件变量;
-
不足:
- 未修改的组件,有覆盖不全的情况,需要一一排查,比较耗时;
- 不够智能化,element-plus中组件变量未继承自全局变量;
-
相关链接:
-
element-plus issues中很多人,遇到了这个问题,暂时无法很好地解决;
-
contributor 给出了建议:
-
We are trying a new way to remove some variables and be repeatedly packaged. We will try to reduce the css var exposed by each component, so as to achieve the convenience of custom variables, and at the same time, there are as few variables as possible. Before that, you can temporarily downgrade back to beta.55. When the optimization of the variables is completed, we will have a complete migration document. -
以及解释了为什么button组件是局部变量的原因:
-
Unfortunately, the variables in button use sass''s `mix` function to blend the corresponding shadows and dark effects as a percentage, and pure CSS variables can not implement mix functionality. We''re also thinking about how to implement it more gracefully, whether to add a new mixed button variable, or something else. -
以及给的一个暂时解决案例element-plus-vite-starter,实际是方案1和方案2的思路,但是无法做到动态改变主题颜色;
-
思路2:theme-chalk
- 思路:使用theme-chalk 生成最终css,分别生成几种主题色的包,切换主题色时,动态加载对应css,覆盖生效;
- 采用方法:
- 采用element-plus中方案四:实际上方案四中使用的element-theme-chalk主题,是基于element-ui 版本
v2.0+的,生成的css在用到element-plus中,样式会有兼容性的问题; - element-plus中theme-chalk文件中,已有写好的通过gulp,打包生成主题的代码,在此基础上改写成可以动态生成css的项目;
- 采用element-plus中方案四:实际上方案四中使用的element-theme-chalk主题,是基于element-ui 版本
- 解决:
- 1、因为项目可能被引入到其他项目,或者独立存在,需要拷贝新的element-plus的scss文件;
- 2、将common/var.scss 文件进行改为 var-origin.scss,做为引入之用;
- 3、创建var-gen模板文件,引用./var-origin.scss,重置scss变量;
scss代码解读复制代码
@forward "./var-origin.scss" with ( $colors:( ''primary'': ( ''base'': $THEME_MODE, //red ... ) ... ), ... ) - 3、基于var-gen.scss文件,通过gulp-replace,可以将$THEME_MODE等自定义变量,替换为对应主题颜色配置值,生成common/var.scss文件;
- 4、进行打包,将scss文件编译为css文件,输出指定到目录;
- 5、在切换主题时,加载将对应的主题css文件,实现动态主题切换;
后续优化
- 1、发布类似 element-theme 的 npm 包,命令行打包生成css文件,从根文件element-plus拷贝scss文件;
- 2、优化自定义变量配置,可以将scss变量写在文件中,读取文件,生成var.scss;
- 3、优雅展示输出提醒;