在2022年了,前端页面主题切换的实现方法有很多,今天我来讲一下通过css变量+setProperty来实现主题切换。具体其他的方法就不讲了,有感兴趣的可以自行了解
前言
这篇文章主要介绍怎么实现主题切换,现在市面上基本上绝大部分web和app都支持主体切换,像微信啊,ios啊 都有什么深色模式,浅色模式。更有甚者,还有定制,可以自定义颜色。
市面上常见的换肤功能主要有以下2种:
- 网站自带几套固定主题,用户只能选择有限的几个主题。
- 主题色由用户随意更改,真正做到用户的个性化定制。
今天我通过css变量来实现换肤,再换肤之前,需要先讲解一下css变量。
CSS变量
CSS变量(官方称为自定义属性)是用户定义的值,它可以在你的代码库中设置一次并多次使用。它们使管理颜色、字体、大小和动画值变得更加容易,并确保整个web应用的一致性。
举个例子,你可以将品牌颜色设置为一个CSS属性(--primarycolor: #7232FA
),并在任何使用品牌颜色的组件或样式中使用这个值(background: var(--primarycolor);
)。
除了更加简洁以及不重复的代码,CSS变量可用于构建调色板,提高响应能力,并创建动态类型系统。
var()函数
var() 函数用于插入 CSS 变量的值。
CSS 变量可以访问 DOM,这意味着您可以创建具有局部或全局范围的变量,使用 JavaScript 来修改变量,以及基于媒体查询来修改变量。
使用 CSS 变量的一种好方法涉及设计的颜色。您可以将它们放在变量中,而不必一遍又一遍地复制和粘贴相同的颜色。
var() 如何工作
首先:CSS 变量可以有全局或局部作用域。
全局变量可以在整个文档中进行访问/使用,而局部变量只能在声明它的选择器内部使用。
如需创建具有全局作用域的变量,请在 :root 选择器中声明它。 :root 选择器匹配文档的根元素。
如需创建具有局部作用域的变量,请在将要使用它的选择器中声明它。
下面的例子与上面的例子相同,但是在这里我们使用 var() 函数。
首先,我们声明两个全局变量(–blue 和 --white)。然后,我们使用 var() 函数稍后在样式表中插入变量的值:
:root {--blue: #1e90ff;--white: #ffffff;
}
body { background-color: var(--blue); }
h2 { border-bottom: 2px solid var(--blue); }
.container {color: var(--blue);background-color: var(--white);padding: 15px;
}
button {background-color: var(--white);color: var(--blue);border: 1px solid var(--blue);padding: 5px;
}
这样,当我们想要修改变量值,只需要修改一个地方就可以
前端换肤demo
介绍完css变量,接下来我们进入实战。先搭建一个基础的架子,有了好的架子才能实现换肤,先创建index.html文件
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><link rel="stylesheet" href="./index.css"><script src="./index.js"></script><link rel="stylesheet" href="../img/icon.svg">
</head>
<body><!-- 头部 --><header><img class="logo" src="../img/D-logo.svg" alt=""><ul class="nav"><li>云居故里</li><li>柚子无敌</li><li>数据中心</li></ul></header><!-- container --><div class="container"><!-- 侧边栏 --><aside><ul class="sub_nav"><li><img class="svg" src="../img/案例展示.svg">我的喜欢</li><li><img class="svg" src="../img/gongyizhanshi.svg">我的收藏</li><li><img class="svg" src="../img/guanzhugongzhonghao.svg">我的查看</li><li><img class="svg" src="../img/lunbobanner.svg">个人中心</li><li><img class="svg" src="../img/weiguanxinxi.svg">福利中心</li><li><img class="svg" src="../img/xuanfuanniu.svg">个人设置</li><li><img class="svg" src="../img/youhuiquan.svg">朋友推荐</li><li><img class="svg" src="../img/guanzhutiao.svg">朋友圈</li></ul></aside><!-- 主体 --><article><div class="card_container"><div class="card"><div class="header"><span>Yyou Design</span><span class="more">更多</span></div><div class="body">Yyou Design是由互娱社区前端团队与 UED团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</div></div><div class="card"><div class="header"><span>Yyou Design</span><span class="more">更多</span></div><div class="body">Yyou Design是由互娱社区前端团队与 UED团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</div></div><div class="card"><div class="header"><span>Yyou Design</span><span class="more">更多</span></div><div class="body">Yyou Design是由互娱社区前端团队与 UED团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</div></div></div><button>+ 添加card</button></article></div>
</body>
</html>
index.css文件
* {margin: 0;padding: 0;box-sizing: border-box;font-size: 16px;
}
s
head, body {width: 100vw;height: 100vh;overflow: hidden;
}
ul li {list-style: none;cursor: pointer;
}
.svg {width: 24px;height: 24px;margin-right: 4px;
}
header {display: flex;position: relative;align-items: center;height: 48px;width: 100%;font-size: 14px;color: #87898b;background-color: #fff;box-shadow: rgb(0 0 0 / 5%) 0px 4px 10px;
}
header .logo {width: 220px;height: 80%;
}
header .nav {display: flex;height: 100%;align-items: center;
}
header .nav li {position: relative;padding: 6px 12px;margin-right: 18px;font-size: 14px;background-color: #fff;border-radius: 1rem;
}
header .nav li:hover {color: #3375f1;
}
header .nav li::after {position: absolute;content: '';width: 100%;height: 2px;bottom: 0px;left: 0;background-color: #3375f1;transition: all .5s ease;transform: scale(0);
}
header .nav li:hover::after {transform: scale(1);
}
.container {display: flex;height: calc(100% - 60px);
}
.container aside {width: 220px;padding: 8px;height: 100%;background-color: #fafcff;border-right: 1px solid #e9ebee;
}
.container aside .sub_nav li {display: flex;align-items: center;width: 100%;padding: 7px 20px;margin-bottom: 12px;font-size: 14px;border-radius: 4px;
}
.sub_nav li:hover {background-color: #ecf5fe;
}
.container article {flex: 1;height: 100%;margin: 20px 20px;
}
.card_container {display: flex;
}
article .card {cursor: pointer;width: 340px;height: 200px;font-size: 14px;border: 1px solid #ededee;margin-right: 40px;border-radius: 4px;transition: all .5s ease;/* box-shadow: rgb(0 0 0 / 5%) 0px 4px 10px; */
}
.card .header {color: #1d1f23;display: flex;font-size: 14px;font-weight: 700;align-items: center;padding: 0 16px;height: 56px;justify-content: space-between;border-bottom: 1px solid #ededee;
}
.card .header .more {font-weight: 400;color: #3375f1;
}
.card .body {padding: 10px 16px;font-size: 14px;color: #87898b;
}
article .card:hover {box-shadow: rgb(0 0 0 / 5%) 0px 4px 10px;
}
button {cursor: pointer;width: 96px;height: 32px;border: 0px;margin-top: 20px;border-radius: 4px;background-color: #3375f1;font-size: 14px;color: #fff;
}
写好html和css后,页面大概长这样子

基本页面搭建完后,我们要实现换肤,首先得有个button,就添加card这个按钮旁边吧
<button>+ 添加card</button><button>切换简约风格</button><button>切换暗黑风格</button><button>切换炫彩风格</button>
按钮有了,接下来我们得把css里需要动态变化的量提取出来,换成var()
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><!-- <link rel="stylesheet" href="./index.css"> --><style> * {margin: 0;padding: 0;box-sizing: border-box;font-size: 16px;}:root {--theme_btn: #3375f1;--theme_shadow: rgb(0 0 0 / 5%) 0px 4px 10px;--theme_size_color: #87898b;--theme_card_bgc: #fff;--theme_aside_bgc: #fafcff;--theme_article_bgc: #fff;--theme_size: #000;}head,body {width: 100vw;height: 100vh;overflow: hidden;}ul li {list-style: none;cursor: pointer;}.svg {width: 24px;height: 24px;margin-right: 4px;}header {display: flex;position: relative;align-items: center;height: 48px;width: 100%;font-size: 14px;color: var(--theme_size_color);background-color: var(--theme_card_bgc);box-shadow: var(--theme_shadow);}header .logo {width: 220px;height: 80%;}header .nav {display: flex;height: 100%;align-items: center;}header .nav li {position: relative;padding: 6px 12px;margin-right: 18px;font-size: 14px;background-color: #fff;border-radius: 1rem;}header .nav li:hover {color: var(--theme_btn);}header .nav li::after {position: absolute;content: '';width: 100%;height: 2px;bottom: 0px;left: 0;background-color: var(--theme_btn);transition: all .5s ease;transform: scale(0);}header .nav li:hover::after {transform: scale(1);}.container {display: flex;height: calc(100% - 48px);}.container aside {width: 220px;padding: 8px;height: 100%;color: var(--theme_size);background-color: var(--theme_aside_bgc);border-right: 1px solid #e9ebee;}.container aside .sub_nav li {display: flex;align-items: center;width: 100%;padding: 7px 20px;margin-bottom: 12px;font-size: 14px;border-radius: 4px;}.sub_nav li:hover {background-color: #ecf5fe;}.container article {flex: 1;height: 100%;padding: 20px 20px;background-color: var(--theme_article_bgc);}.card_container {display: flex;}article .card {cursor: pointer;width: 340px;height: 200px;font-size: 14px;border: 1px solid #ededee;margin-right: 40px;border-radius: 4px;transition: all .5s ease;background-color: var(--theme_card_bgc);/* box-shadow: rgb(0 0 0 / 5%) 0px 4px 10px; */}.card .header {color: var(--theme_size);display: flex;font-size: 14px;font-weight: 700;align-items: center;padding: 0 16px;height: 56px;justify-content: space-between;border-bottom: 1px solid #ededee;}.card .header .more {font-weight: 400;color: var(--theme_btn);}.card .body {padding: 10px 16px;font-size: 14px;color: var(--theme_size_color);}article .card:hover {box-shadow: var(--theme_shadow);}button {cursor: pointer;width: 96px;height: 32px;border: 0px;margin-top: 20px;border-radius: 4px;background-color: var(--theme_btn);font-size: 14px;color: #fff;} </style><script src="./index.js"></script>
</head>
<body><!-- 头部 --><header><img class="logo" src="../img/D-logo.svg" alt=""><ul class="nav"><li>云居故里</li><li>柚子无敌</li><li>数据中心</li></ul></header><!-- container --><div class="container"><!-- 侧边栏 --><aside><ul class="sub_nav"><li><img class="svg" src="../img/案例展示.svg">我的喜欢</li><li><img class="svg" src="../img/gongyizhanshi.svg">我的收藏</li><li><img class="svg" src="../img/guanzhugongzhonghao.svg">我的查看</li><li><img class="svg" src="../img/lunbobanner.svg">个人中心</li><li><img class="svg" src="../img/weiguanxinxi.svg">福利中心</li><li><img class="svg" src="../img/xuanfuanniu.svg">个人设置</li><li><img class="svg" src="../img/youhuiquan.svg">朋友推荐</li><li><img class="svg" src="../img/guanzhutiao.svg">朋友圈</li></ul></aside><!-- 主体 --><article><div class="card_container"><div class="card"><div class="header"><span>Yyou Design</span><span class="more">更多</span></div><div class="body">Yyou Design是由互娱社区前端团队与 UED团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</div></div><div class="card"><div class="header"><span>Yyou Design</span><span class="more">更多</span></div><div class="body">Yyou Design是由互娱社区前端团队与 UED团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</div></div><div class="card"><div class="header"><span>Yyou Design</span><span class="more">更多</span></div><div class="body">Yyou Design是由互娱社区前端团队与 UED团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</div></div></div><button>+ 添加card</button><button id="common">切换简约风格</button><button id="block">切换暗黑风格</button><button id="colorful">切换炫彩风格</button></article></div>
</body>
</html>
注意,这里我们把index.css的代码,全部通过内嵌放到了index.html中,这是因为后面如果用js修改变量的话,如果是link引入的样式,受游览器同源影响,是无法修改的,会导致报错。所以我们把css放到了html中
有了css变量,最后我们只需要写js代码,实现动态切换就可以了
// index.js
window.onload = function () {const commonBtn = document.getElementById('common');const blockBtn = document.getElementById('block');const colorfulBtn = document.getElementById('colorful');const ThemeSwitch = {common: {'--theme_btn': '#3375f1','--theme_shadow': 'rgb(0 0 0 / 5 %) 0px 4px 10px','--theme_size_color': '#87898b','--theme_card_bgc': '#fff','--theme_aside_bgc': '#fafcff','--theme_article_bgc': '#fff','--theme_size': '#000',},block: {'--theme_btn': 'purple','--theme_shadow': 'rgb(255 255 255 / 20 %) 0px 4px 10px','--theme_size_color': 'pink','--theme_card_bgc': 'block','--theme_aside_bgc': '#000','--theme_article_bgc': '#000','--theme_size': '#fff',},colorful: {'--theme_btn': 'skyblue','--theme_shadow': 'rgb(0 0 0 / 5 %) 0px 4px 10px','--theme_size_color': 'orange','--theme_card_bgc': 'skyblue','--theme_aside_bgc': 'orange','--theme_article_bgc': 'pink','--theme_size': '#000',},}console.log(document.body.style)commonBtn.addEventListener('click', (e) => {Object.keys(ThemeSwitch.common).reduce((acc, item) => {document.styleSheets[0].cssRules[0].style.setProperty(item, ThemeSwitch.common[item])}, [])})console.log(1)blockBtn.addEventListener('click', (e) => {Object.keys(ThemeSwitch.block).reduce((acc, item) => {document.styleSheets[0].cssRules[0].style.setProperty(item, ThemeSwitch.block[item])}, [])})colorfulBtn.addEventListener('click', () => {Object.keys(ThemeSwitch.colorful).reduce((acc, item) => {document.styleSheets[0].cssRules[0].style.setProperty(item, ThemeSwitch.colorful[item])}, [])})
}
最后,让我们来看一下效果图
最后
最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。
有需要的小伙伴,可以点击下方卡片领取,无偿分享