使用 css/less 动态更换主题色(换肤功能)
前言
说起换肤功能,前端肯定不陌生,其实就是颜色值的更换,实现方式有很多,也各有优缺点
一、看需求是什么
一般来说换肤的需求分为两种:
1. 一种是几种可供选择的颜色/主题样式,进行选择切换,这种可供选择的主题切换不会很多
2. 另一种是需要自定义色值,或者通过取色板取色,可供选择的范围就很大了
二、如何实现
1. 对于可供选择的颜色/主题样式换肤的实现
一个全局class控制样式切换
切换的时候js控制样式的切换
JS改变href属性值切换样式表,例如:
<link id="skincolor" href="skin-default.css" rel="stylesheet" type="text/css">
document.getElementById('#skincolor').href = 'skin-red.css';
这种方式需要维护几个主题样式表,js点击切换的时候通过改变css样式表链接来实现。 例如这个 demo
这种实现对于,颜色和主题多了的时候,维护起来就很麻烦,需要同时维护 n 个样式文件,并且使用JS改变href属性会带来加载延迟,样式切换不流畅,体验也不好。
但如果是有包含不同复杂背景图片切换的时候,这种方式可以实现,但其他如下面要说的css变量 less modifyVars 就无法实现了
HTML 的 rel 属性下的 alternate 实现: MDN Alternative style sheets
示例:
<link href="reset.css" rel="stylesheet" type="text/css">
<link href="default.css" rel="stylesheet" type="text/css" title="Default Style">
<link href="fancy.css" rel="alternate stylesheet" type="text/css" title="Fancy">
<link href="basic.css" rel="alternate stylesheet" type="text/css" title="Basic">
所有样式表都可分为3类:
- 没有title属性,rel属性值仅仅是stylesheet的
<link>无论如何都会加载并渲染,如reset.css; - 有title属性,rel属性值仅仅是stylesheet的
<link>作为默认样式CSS文件加载并渲染,如default.css; - 有title属性,rel属性值同时包含alternate stylesheet的
<link>作为备选样式CSS文件加载,默认不渲染,如red.css和green.css;
alternate意味备用,相当于是 css 预加载进来备用,所以不会有上面那种切换延时
但怎么用呢?禁用掉?
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
link 的 disabled 属性

使用JavaScript代码修改<link>元素DOM对象的disabled值为false,可以让默认不渲染的CSS开始渲染。实现 demo
2. 对于制定动态色值换肤的实现
如果是要实现动态换肤,自定义色值,那上面的几种方式就不适合了。
先看下已有的实现有哪些方法
Element-UI 有换肤功能 示例预览
实现原理: 官方解释
- 先把默认主题文件中涉及到颜色的 CSS 值替换成关键词:https://github.com/ElementUI/theme-preview/blob/master/src/app.vue#L250-L274
- 根据用户选择的主题色生成一系列对应的颜色值:https://github.com/ElementUI/theme-preview/blob/master/src/utils/formula.json
- 把关键词再换回刚刚生成的相应的颜色值:https://github.com/ElementUI/theme-preview/blob/master/src/utils/color.js
- 直接在页面上加
style标签,把生成的样式填进去:https://github.com/ElementUI/theme-preview/blob/master/src/app.vue#L198-L211
看这个实现,还是比较麻烦的,想看看还有没有更优雅的方法来实现
Ant Design 的更换主题色功能是用 less 提供的 modifyVars 的方式进行覆盖变量来实现。
less的 modifyVars方法
modifyVars方法是是基于 less 在浏览器中的编译来实现。所以在引入less文件的时候需要通过link方式引入,然后基于less.js中的方法来进行修改变量
less.modifyVars({
'@themeColor': 'blue'
});
link方式引入主题色文件
<link rel="stylesheet/less" type="text/css" href="./src/less/public.less" />
更改主题色事件
// color 传入颜色值
handleColorChange (color) {
less.modifyVars({ // 调用 `less.modifyVars` 方法来改变变量值'
@themeColor':color
})
.then(() => {
console.log('修改成功');
});
};
如果发现项目运行报错如下:
.bezierEasingMixin();
^
Inline JavaScript is not enabled. Is it set in your options?
那可能是没有开启 javascriptEnabled:true
在webpack配置里开启
{
test: /\.less$/,
loader: 'less-loader',
options: {
javascriptEnabled: true
}
},
less方法仅限于用less的项目才能使用,查了下sass是没有类似 less.modifyVars 这种方法的。
那有没有通用一点的方法呢?于是就有了
css 变量方法
如果项目里用的不是less, 那么还是用css的方法,通用且容易操作,使用css变量来进行主题色的修改,替换主题色变量,然后用setProperty来进行动态修改
用法就是给变量加--前缀,涉及到主题色的都改成var(--themeColor)这种方式
用之前看下兼容性

https://caniuse.com/#search=CSS%20Variables
大部分主流浏览器还是支持的,而且主要是操作起来够简便。
用法举例:
body{
--themeColor:#000;
}
使用:
.main{
color: var(--themeColor);
}
要修改主题色的话:
document.body.style.setProperty('--themeColor', '#ff0000');
总结
一个看似简单的需求可以实现的方法有很多,具体怎么实现要结合需求来动态进行选择。
参考:
https://juejin.im/post/5ca41617f265da3092006155
https://www.zhangxinxu.com/wordpress/2019/02/link-rel-alternate-website-skin/
使用 css/less 动态更换主题色(换肤功能)的更多相关文章
- 利用CSS预处理技术实现项目换肤功能(less css + asp.net mvc4.0 bundle)
一.背景 在越来越重视用户体验的今天,换肤功能也慢慢被重视起来.一个web系统用户可以选择一个自己喜欢的系统主题,在用户眼里还是会多少加点分的.我们很开心的是easyui v1.3.4有自带defau ...
- Element-UI动态更换主题
参考:vue-基于elementui换肤[自定义主题] 实践: 需求1.后期维护主题色不更换: 直接在线主题生成工具下载,在APP.VUE引入:(注意Element UI 版本1.3?2.0) 需求 ...
- 【转】Javascript+css 实现网页换肤功能
来源:http://www.php100.com/html/webkaifa/DIV_CSS/2008/1014/2326.html Html代码部分: 1.要有一个带id的样式表链接,我们要通过操作 ...
- Android 切换主题以及换肤的实现
Android 切换主题以及换肤的实现 一.介绍 现在市面上有很多 APP 有切换主题和皮肤的功能!特别是阅读类的 APP! 上面两张图分别是 知乎 APP 和Fuubo APP的两张截图!都带有切换 ...
- 基于webpack4+vue-cli3项目的换肤功能
起因 最近因公司需求,需要实现主题换肤功能,不仅仅是颜色的更改,还需要包括图片,字体等文件等更换,因此在百度里各种实现方案后,决定根据scss+style-loader/useable做换肤. 项目开 ...
- Flex AIR应用换肤功能(Android和IOS)
说明 换肤功能,即将整个应用的皮肤都进行更换,其实质,是动态加载swf文件的过程,而这些swf文件则有css文件编译而来. 关于换肤功能,在android和ios系统的实现方式是不同的.主要原因,是因 ...
- JS实现网页换肤功能效果
网页换肤的基本原理 使用 JS 切换对应的 CSS 样式表.例如hao123首页的右上方就有网页换肤功能.除了切换 CSS 样式表文件之外,通常的网页换肤还需要通过 Cookie 来记录用户之前更换过 ...
- cookie换肤功能
<div class="selectSkin"> <input id="red" class="themeBtn" typ ...
- 用js来实现页面的换肤功能(带cookie记忆)
用js来实现页面的换肤功能 js实现换肤功能的实现主要是通过利用js控制CSS来实现的.大致的实现原理是这样的, 1.先定义一个页面基本样式style.css来确定div的宽高等属性,使得整个页面的D ...
随机推荐
- Java调用Http/Https接口(4)--HttpClient调用Http/Https接口
HttpClient是Apache HttpComponents项目下的一个组件,是Commons-HttpClient的升级版,两者api调用写法也很类似.文中所使用到的软件版本:Java 1.8. ...
- Android为TV端助力之QQ空间热更新技术
直接上代码 package com.enjoy.patch; import android.content.Context;import android.os.Build;import android ...
- mysql表的连接
目录 1.笛卡尔积:将两表所有的数据一一对应,生成一张大表 2.连表查询 1.inner join 内连接 2.left join 左连接(left join左边的表为主表,主表记录必须全部显示,辅表 ...
- Linux正则表达式、shell基础、文件查找及打包压缩
Linux正则表达式.shell基础.文件查找及打包压缩 一.正则表达式 Linux正则表达式分为2类: 1.基本正则表达式(BRE) 2.扩展正则表达式(ERE) 两者的区别: 1.使用扩展正则表达 ...
- 接口测试 dubbo 接口测试技术
本文转自测试之家 https://testerhome.com/topics/10481 dubbo是阿里巴巴开源的一套rpc方案,以为理念很契合微服务,这几年很火,用户里面不凡京东,当当,去哪儿等大 ...
- sq分页
create proc RowNumber @pageindex int,@pagesize int AS BEGIN select * from (select ROW_NUMBER() OVER( ...
- jquery 子元素 后代元素 兄弟元素 相邻元素
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content ...
- SQL进阶系列之6用关联子查询比较行与行
写在前面 使用SQL对同一行数据进行列间的比较很简单,只需要在WHERE子句里写上比较条件就可以了,对于不同行数据进行列间比较需要使用自关联子查询. 增长.减少.维持现状 需要用到行间比较的经典场景是 ...
- Cisco网络模拟器踩坑记录
1.在我们新建一个拓扑图的时候,选择设备之间的连线种类有时会导致线路不通的情况(两个端口上为红色点)这时候建议拆除这条线后选择闪电标记 的万能线帮助我们自动创建连线(这时就能根据它显示的线条种类得知应 ...
- Redis.Memcache和MongoDB区别?
Memcached的优势: Memcached可以利用多核优势,单吞吐量极高,可以达到几十万QPS(取决于Key.value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右.)适用 ...