css var实现网页换肤
前情
最近在做需求开发,要求根据后台传来的配置对网页换肤,按以往的换肤思路应该是写好几套样式做切换达到换肤效果,但是现在想做到能根据后台配置动态修改。
原理
通过css3新增变量特性,把颜色定义为变量再全局使用,在想更改颜色的时候,我们只要修改对应变量对应的颜色就能全局换肤,主要原理演示代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style type="text/css">
:root {
--main-bg-color: red;
}
.test{
width: 500px;
height: 100px;
background-color: green;
background-color: var(--main-bg-color);
}
</style>
</head>
<body>
<div class="test"></div>
</body>
</html>
演示地址:https://jsbin.com/lozizajuva/edit?html,output
换肤实战
- 通过颜色配置表生成一个包含所有css变量的style插入到head中
- 所有css中需要进行颜色替换的都通过css变量来设置
- 动态更换主题的话只要替换上面生成style里的内容即可
演示代码
html结构
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
body{
--test-var: 'green';
}
.test{
width: 500px;
height: 100px;
/* 低版本不兼容的浏览器也有个默认颜色 */
background-color: blue;
background-color: var(--main-color)
}
.test_in{
width: 100px;
height: 50px;
line-height: 50px;
font-size: 14px;
background-color: #dddddd;
/* 低版本不兼容的浏览器也有个默认颜色 */
color: blue;
color: var(--main-color);
}
</style>
</head>
<body>
<div class="test">
<div class="test_in">css var换肤</div>
</div>
<select id="themeSelect">
<option value ="deault">默认</option>
<option value ="red">红色</option>
<option value="green">绿色</option>
</select>
</body>
</html>
javascript
// 颜色配置表,测试数据,正常是从服务端过来的
const THEME_CONFIG = {
"default": {
"--main-color": "blue"
},
"red": {
"--main-color": "red"
},
"green": {
"--main-color": "green"
}
}
// 存储当前用的是什么色系
let currentConfig = THEME_CONFIG['default'];
// 备份styles
let stylesBackups = null;
/**
* 生成主题代码段
* @param {Object} config
* @returns
*/
function createThemeStyle(config) {
let result = `
:root {
--main-color: ${config['--main-color']};
}`
return result;
}
/**
* 插入主题style段
* @param {String} styleString
*/
function insertThemeStyle(styleString) {
let styleTag = document.querySelector('#themeStyleTag');
if (!styleTag) {
styleTag = document.createElement('style');
styleTag.id = 'themeStyleTag';
styleTag.setAttribute('type', 'text/css');
document.getElementsByTagName('head')[0].insertBefore(styleTag, document.getElementsByTagName('style')[0]);
}
styleTag.innerHTML = styleString;
}
/**
* 判断css变量是否被支持
*/
function cssVarIsSupport() {
var testVar = getComputedStyle(document.body).getPropertyValue("--test-var");
return testVar ? true : false;
}
/**
* 解决兼容,根据主题配置生成正则
* @returns string
*/
function createStyleRegex() {
let regexStr = '';
let varList = Object.keys(currentConfig);
for(let i=0,len=varList.length; i<len; i++) {
regexStr += `var\\(${varList[i]}\\)${i<len-1 ? '|' : ''}`;
};
return regexStr;
}
/**
* css变量兼容处理-第一次
*/
function compatibleProcessingCssVar() {
let styles = document.getElementsByTagName('head')[0].getElementsByTagName('style');
stylesBackups = {};
// 生成正则匹配规则字符串
let regexStr = createStyleRegex();
// 遍历所有style标签替换
for(let i=1,len=styles.length; i<len; i++) {
let item = styles[i];
let replaceReg = new RegExp(regexStr, 'g');
let styleStr = item.innerHTML;
if (!replaceReg.test(styleStr)) {
continue;
}
if (!stylesBackups['theme'+i]) {
item.setAttribute('id', 'theme'+i);
stylesBackups['theme'+i] = styleStr;
}
styleStr = styleStr.replace(replaceReg, function(mactchStr) {
return currentConfig[mactchStr.split(/\(|\)/)[1]];
});
item.innerHTML = styleStr;
}
}
/**
* 解决兼容浏览器的动态换肤问题
* css变量兼容处理-后面不需再去获取所有style,通过从内存中拿缓存的style来做字符串替换
*/
function compatibleProcessingCssVarFromCache() {
// 生成正则匹配规则字符串
let regexStr = createStyleRegex();
let styleKeys = Object.keys(stylesBackups);
// 遍历所有style标签替换
for(let i=1,len=styleKeys.length; i<len; i++) {
let key = styleKeys[i];
let styleStr = stylesBackups[key];
let replaceReg = new RegExp(regexStr, 'g');
styleStr = styleStr.replace(replaceReg, function(mactchStr) {
return currentConfig[mactchStr.split(/\(|\)/)[1]];
});
document.getElementById(key).innerHTML = styleStr;
}
}
/**
* 适配主题
* @param {string} theme
*/
function adaptationTheme(theme) {
// 获取颜色列表
currentConfig = THEME_CONFIG[theme];
// 对于兼容css var的浏览器
if (cssVarIsSupport()) {
// 生成style
let styleString = createThemeStyle(currentConfig);
// 插入style中
insertThemeStyle(styleString)
} else {
// 对于不兼容css var的浏览器(chrome49、ie15以下)
if (stylesBackups) {
compatibleProcessingCssVarFromCache();
return;
}
compatibleProcessingCssVar();
}
}
window.onload = function(){
adaptationTheme('default');
// 动态更换主题
document.querySelector('#themeSelect').addEventListener('change', function() {
adaptationTheme(this.value)
}, false)
}
注意事项:
如果想兼容低版本浏览器则需要所有样式通过style写入,因为在做兼容处理的时候,是通过js代码替换掉style标签里的css变量来做兼容处理的,上面代码有做低版本兼容,对于不需要兼容低版本浏览器的,上面代码可以删减掉兼容代码。
演示地址:https://jsbin.com/tetuguxifi/1/edit?html,js,output
css var实现网页换肤的更多相关文章
- js网页换肤
使网页背景颜色可选黄/粉 <html> <head> <meta charset="utf-8"> <meta name="ge ...
- JS实现网页换肤功能效果
网页换肤的基本原理 使用 JS 切换对应的 CSS 样式表.例如hao123首页的右上方就有网页换肤功能.除了切换 CSS 样式表文件之外,通常的网页换肤还需要通过 Cookie 来记录用户之前更换过 ...
- JavaScript网页换肤
使网页背景颜色可选黄/粉 <!doctype html> <html> <head><title>网页换肤</title></head ...
- 【转】Javascript+css 实现网页换肤功能
来源:http://www.php100.com/html/webkaifa/DIV_CSS/2008/1014/2326.html Html代码部分: 1.要有一个带id的样式表链接,我们要通过操作 ...
- 基于js的网页换肤(不需要刷新整个页面,只需替换css文件)
1. [代码][JS]代码 <HTML><HEAD><link ID="skin" rel="stylesheet" typ ...
- 网页换肤,模块换肤,jQuery的Cookie插件使用(转)
具体效果如下: 第一次加载如下图: 然后点击天蓝色按钮换成天蓝色皮肤如下图: 然后关闭网页重新打开或者在打开另一个网页如下图: 因为皮肤用Cookie保存了下来,所以不会重置 具体的实现代码如下: & ...
- jquery网页换肤+jquery的cookie+动态调用css样式文件,可以的
比较具有参考性,代码全贴(当然,还需要一张图片需要的留个邮箱,看到就发) 贴在这儿吧,修改一下css的引用位置应该可以用 <%@ page language="java" c ...
- css, js 项目练习之网页换肤
首先,该练习参考自:https://www.jianshu.com/p/2961d9c317a3 我就直接上代码了(颜色可以自己调). HTML: <nav> <li>< ...
- 网上找到的一个jquery版网页换肤特效
这个跟我之前在锋利的JQuery那本书里看到的那个一模一样. <!DOCTYPE html> <html> <head> <meta name="& ...
- 网页换肤:原生js与jq
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- QT原理与源码分析之QT对象类型QObject源码中的间接的设计思想
这一篇文章介绍QT框架中QT对象类型QObject类型的源代码在设计上的一个比较优秀的设计思想. QObject类型定义 QObject 直接来看QObject的源代码.为了表达更简洁更直观,这里省略 ...
- 暑假集训SCP提高模拟10
我(看着百度百科):我已经知道这场谁组的题了 CTH: 谁 我:你想想,能在模拟赛里塞四道数学题还玩邦的,还能有谁 CTH: 我不知道 我:我不知道 CTH: 我知道了 我:我知道了 我:我是 Bob ...
- Adobe Pr 软件报错,此效果需要GPU加速
事件起因: 某同事使用PR软件报错,报错截图如下: 解决办法: 1.在pr菜单栏选择文件-项目设置-常规-视频渲染和回放-渲染程序,切换到Mercury Playback Engine GPU加速 ...
- 如何使用hardware breakpoint
要使用内核的硬件断点(hardware breakpoint)来定位内核模块中的内存访问问题,你可以通过以下步骤进行设置和调试. 1. 确定要监控的内存地址 首先,你需要确定你想要监控的内存地址.这可 ...
- /proc/sys/vm 使用
这些参数主要是用来调整virtual memory子系统的行为以及数据的写出(从RAM到ROM). 这些节点(参数)的默认值和初始化的过程大部分都可以在mm/swap.c中找到. 目前,/proc/s ...
- CMake 属性之目录属性
[写在前面] CMake 的目录属性是指在特定目录(及其子目录)范围内有效的设置. 这些属性不同于全局变量或目标(Target)属性,它们提供了一种机制,允许开发者为项目中的不同部分定义不同的构建行为 ...
- 如何在kubernetes环境中共享GPU
随着人工智能和大模型的快速发展,云上GPU资源共享变得必要,因为它可以降低硬件成本,提升资源利用效率,并满足模型训练和推理对大规模并行计算的需求. 在kubernetes内置的资源调度功能中,GPU调 ...
- 探索 Kubernetes 持久化存储之 Rook Ceph 初窥门径
在 Kubernetes 生态系统中,持久化存储是支撑业务应用稳定运行的基石,对于维护整个系统的健壮性至关重要.对于选择自主搭建 Kubernetes 集群的运维架构师来说,挑选合适的后端持久化存储解 ...
- KubeSphere 边缘节点 IP 冲突的分析和解决思路分享
在上一篇监控问题排查的文章中,笔者分析了 KubeSphere 3.1.0 集成 KubeEdge 中的边缘监控原理和问题排查思路,在介绍 EdgeWatcher 组件时提到了"边缘节点的内 ...
- 中国移动基于 Kubernetes 的物联网边缘计算应用实践
作者:何毓川,中移物联网,云计算开发高级工程师 EdgeBox简介 中移物联网是中国移动集团在物联网方向的专业研发子公司,在各个垂直行业都有非常丰富和完成的解决方案. 本文通过中移物联网的物联网边缘计 ...