前端主题换肤技术总结

lxf2023-05-14 01:31:44

由于平常总是遇到各类换肤的需求,在此做下大概总结,以便对各种情况的换肤场景进行参考。

换肤场景

换肤常见的场景有以下几种:

  • 黑夜/白天模式切换
  • 主题换肤,如QQ邮箱的主题皮肤
  • 客制化配色,如同一应用针对不同渠道定制的不同配色

其中黑夜/白天模式切换与主题换肤之间的概念类似,只是交互逻辑上略有区别。

换肤需求

换肤根据需求来讲可以分为:

  • 静态换肤,提供几种可选择的颜色/主题样式,进行选择切换,一般可供选择的主题样式不会太多
  • 动态换肤,可自定义色值,可通过取色板取色或者后端接口下发,可选择的范围比较大

思路

讲完了换肤类型,接下来分析几种常规的换肤手段

1.Less 变量/ Sass 变量

可以说是是最常见的换肤手段,利用 Less 变量对应用样式进行重新定义,如:

// variable-theme.less
@color-primary: #E3454B;
@color-up: #E53939;
@color-down: #43A047;
@color-flat: #545A71;
@color-buy: #E63232;
@color-sell: #2E83F2;

然后在对应属性下使用:

// button.less
.button-primary {
	background-color: @color-primary;
}

但是这时候我们发现,Less 变量只能影响 CSS,不能影响 JS,这时候如果遇到需求需要配置如图表样式、JS 生成的 style 样式等 JS 控制的样式时,Less 变量就变得力不从心了。查阅了一系列资料得知,CSS Modules 中有一个简洁的实用指令,称为 :export,:export 指令的工作原理基本上类似于 ES6 的 export 关键字。在 webpack 的帮助下,:export 将导出一个对象,其中包含要在 JS 中使用的变量名称及其关联值,这些值都会作为字符串导出。 export.less:

@import "./variable-theme.less";

:export {
    colorPrimary: @color-primary;
    colorUp: @color-up;
    colorDown: @color-down;
    colorFlat: @color-flat;
    colorBuy: @color-buy;
    colorSell: @color-sell;
}

index.js

import variablesLess from './export.less';

// 导出变量
export default variablesLess;

注意,如果要使用 :export,且当前 css-loader 版本 >= 4,需要将其配置项 "modules.mode" 修改为 "icss"。

以上步骤,我们已经完成了对项目的绝大多数内容的配置,这时候需要的就是通过各种方式改变 variable-theme.less** **文件中的 Less 变量即可,常见的方式是通过 webpack 改变引用的变量文件,如 variable-theme.less,来进行变量替换。或者预先引用不同主题变量文件,打出不同的css文件,在运行时通过读取 url 参数等方式进行引用替换: 前端主题换肤技术总结 以上只是两种常见的实现方式,这里不针对展开赘述,可根据实际场景自行选择方案。

2.CSS变量+css-vars-ponyfill

先来说下 CSS自定义变量 ,它让我拥有像 Less/Sass 那种定义变量并使用变量的能力,声明变量的时候,变量名前面要加两根连词线( --),在使用的时候只需要使用 var() 来访问即可,看下效果:前端主题换肤技术总结 使用 CSS自定义变量 的好处就是我们可以使用 JS 来改变这个变量:

  • 使用 document.body.style.setProperty('--bg' ,'#ff0000' );来设置变量
  • 使用 document.body.style.getPropertyValue('--bg' ); 来获取变量
  • 使用 document.body.style.removeProperty('--bg' ); 来删除变量

有了如上的准备,我们基于 css变量 来实现的换肤就有思路了:将 CSS 中与换肤有关的颜色值提取出来放在 :root{} 中,然后在页面上使用 setProperty 来动态改变这些变量值即可。

然而 CSS自定义变量 有个致命的缺点,就是不支持IE和部分低版本的移动端浏览器内核,这个时候就需要使用到 css-vars-ponyfill 这个polyfill来搞定IE了,具体使用方法可参考 换肤解决方案1-css变量法

3.CSS优先级覆盖法

这也是所有方法中最不推荐的一种方法,之所以写出来,是因为前两种方案都是基于改造项目整体的情况下进行的,而优先级覆盖法作为入侵最少的方案,也确实在特殊情况下有一定的用武之地,一句话概括就是创建一份主题包文件,通过对其编写优先级较高的 CSS样式 来覆盖原项目的样式,并使用类似引用不同主题变量文件的方式来进行主题切换。当然,入侵少便意味着耦合高,原样式的些许更改就可能对主题包有破坏性的影响,因此在使用这种方法的时候需要慎重考虑。

总结

除了以上的这些方法外,其实还有很多解决方案,包括针对换肤过程中的触发场景、替换方案、持久化场景等都有各种解法,往后有时间也会慢慢补充上来自己的一些积累。

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!