你了解哪些前端主题的切换方案?
约 1470 字大约 5 分钟
2025-03-15
前端主题切换 是指通过动态改变网页的样式主题,以适应不同的使用场景或用户偏好。常见的实现方式包括使用 CSS 变量、动态引入 CSS 文件、以及使用组件库的主题切换功能。
方式一:CSS 变量+属性切换 最佳方案
该方案通过 CSS 变量定义几套不同的主题颜色变量,在对应的样式下面引用对应的 css 变量,通过 js 来改变根元素的属性,来实现颜色的动态切换
优点:
- 切换无卡顿,不需要重新加载样式文件
- 新增和修改主题方便,将颜色从主题中抽离出来,不同主题间共享 css 布局和 dom 结构的一致性,通过 CSS 变量控制颜色,新增和修改主题非常方便。
缺点:
- 兼容性 ,部分老版本浏览器可能存在兼容性问题
- 首屏加载时间会略微延长
<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CSS 变量切换</title>
<style>
/* 定义变量 */
:root {
--background-color: #fff;
--text-color: #333;
--btn-color: green;
--font-size: 16px;
}
[data-theme="dark"] {
--background-color: #c1c1c1;
--text-color: #fff;
--btn-color: #777;
}
body {
background-color: var(--background-color);
text-align: center;
color: var(--text-color);
font-size: var(--font-size);
padding: 50px;
}
button {
background-color: var(--btn-color);
color: var(--text-color);
font-size: var(--font-size);
padding: 10px 20px;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<h1>CSS 变量切换示例</h1>
<button onclick="toggleTheme()">切换主题</button>
<script>
function toggleTheme() {
const root = document.documentElement;
let theme =
root.getAttribute("data-theme") === "light" ? "dark" : "light";
root.setAttribute("data-theme", theme);
}
</script>
</body>
</html>
类似的方案
在 vue3 项目中,主流的样式切换方案是使用 css 变量 + @vueuse/core
中的 useDark
、toggleDark
来配合切换主题。核心原理是改变 <html>
元素的 class
属性值。
也可以使用 document.documentElement.style.setProperty('--text-color', "red");
实现动态修改主题色
方案二:link 标签动态引入 CSS 文件
其做法就是提前准备好几套CSS
主题样式文件,在需要的时候,创建link
标签动态加载到head
标签中,或者是动态改变link
标签的href
属性。
优点:
- 实现了按需加载,提高了首屏加载时的性能
缺点:
- 加载问题: 动态加载样式文件,如果文件过大网络情况不佳的情况下可能会有加载延迟,导致样式切换不流畅
- 修改维护麻烦: 每个样式一份文件,全部是写死的。新增主题、修改 Dom 结构,可能需要同步修改全部主题 CSS 文件
方案三:引入全部主题 CSS,类名切换
该方案与第一种类似,也是提前准备好几套CSS
主题样式文件,提前全部引入,可以在根元素上设置主题,通过修改根元素的 class 属性,来实现不同的主题样式生效
优点:
- 切换无卡顿,不需要重新加载样式文件
缺点:
- 加载问题: 需要一次性加载全部 CSS 文件,牺牲了首屏加载事件,对网络性能有要求。
- 修改维护麻烦: 每个样式一份文件,全部是写死的。新增和修改样式,可能需要同步修改全部主题 CSS 文件
方式四:Vue3
CSS 中的 v-bind()
单文件组件的 <style>
标签支持使用 v-bind
将 css 和 js 结合起来,动态赋予 css 属性值
<template>
<div class="text">hello</div>
</template>
<script>
export default {
data() {
return {
color: "red",
};
},
};
</script>
<style>
.text {
color: v-bind(color);
}
</style>
方式五:利用 css 预处理器推荐
主要是运用 SCSS
的混合+CSS 类名切换,其原理主要是将使用到 mixin
混合的地方编译为固定的 CSS 以后,再通过类名切换去做样式的覆盖
1、定义主题变量
在 Sass 中,可以使用变量来定义不同主题的颜色、字体等样式。
// 定义默认主题
$themes: (
light: (
primary-color: #ffffff,
secondary-color: #000000,
font-size: 16px,
),
dark: (
primary-color: #000000,
secondary-color: #ffffff,
font-size: 16px,
),
);
2、创建主题混合(Mixin)
使用 @mixin
创建一个混合,用于根据当前主题应用样式。
@mixin theme($theme) {
$primary-color: map-get($theme, primary-color);
$secondary-color: map-get($theme, secondary-color);
$font-size: map-get($theme, font-size);
background-color: $primary-color;
color: $secondary-color;
font-size: $font-size;
}
3、应用主题
在样式表中应用主题。
body {
@include theme(map-get($themes, light)); // 默认使用 light 主题
}
.theme-dark {
@include theme(map-get($themes, dark)); // 使用 dark 主题
}
4、动态切换主题
通过 JavaScript 动态切换 HTML 元素的类名来切换主题。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sass 主题切换</title>
<link rel="stylesheet" href="styles.css" />
<!-- 编译后的 CSS 文件 -->
</head>
<body class="theme-light">
<h1>主题切换示例</h1>
<button onclick="toggleTheme()">切换主题</button>
<script>
function toggleTheme() {
const body = document.body;
if (body.classList.contains("theme-light")) {
body.classList.remove("theme-light");
body.classList.add("theme-dark");
} else {
body.classList.remove("theme-dark");
body.classList.add("theme-light");
}
}
</script>
</body>
</html>
方式六:Node.js 路由拦截 + Cookies推荐
可以通过将主题设置到 cooikes
里,在加载 css 文件时,通过正则匹配到样式文件,后台根据 cookies
里的 theme
值来控制加载不同的主题 css主题文件
返回给前台
router.get(/^\/app(\.*)?.css*$/, function (req, res) {
let theme = req.cookies.theme;
let filePath = "";
let __DEV__ = process.env.NODE_ENV === "development";
if (__DEV__) {
filePath = path.join(Consts.DEV, Consts.STATIC, "css");
} else {
filePath = path.join(Consts.DIST, Consts.STATIC, "css");
}
res.type("text/css; charset=utf-8");
switch (theme) {
case "light":
res.sendFile(path.join(filePath, "app.css"));
break;
case "blue":
res.sendFile(path.join(filePath, "app-blue.css"));
break;
case "dark":
res.sendFile(path.join(filePath, "app-dark.css"));
break;
default:
res.sendFile(path.join(filePath, "app.css"));
}
});
方式七:js 函数动态修改 class推荐
这种情况主要适用于用户自定义主题颜色的情况,通过一个 js 函数来筛选符合条件的 dom 节点,动态修改其主题颜色
更新日志
e7112
-1于