Vue换肤核心是“定义—使用—切换”三步闭环:在:root定义默认CSS变量,用[data-theme]覆盖主题;组件中用var()引用;通过设置document.documentElement.dataset.theme动态切换,并优先用户选择、兼顾系统偏好。

Vue模板中绑定CSS变量实现换肤,核心在于“定义—使用—切换”三步闭环。不依赖第三方库、兼容主流浏览器(IE除外)、响应式生效快,是当前最推荐的方案。
在全局样式中定义主题变量
CSS变量需在:root或带data-theme属性的选择器中声明,确保作用域覆盖全站:
- 基础亮色主题写在
:root里,作为默认值 - 暗色/其他主题用属性选择器覆盖,例如
[data-theme="dark"]或html[data-theme="dark"] - 变量名建议语义化,如
--text-primary、--bg-surface,避免硬编码颜色值
示例:
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
:root {
--text-primary: #333;
--bg-surface: #fff;
--border-base: #e0e0e0;
}
[data-theme="dark"] {
--text-primary: #f0f0f0;
--bg-surface: #1f1f1f;
--border-base: #444;
}
在组件样式中通过var()引用变量
无需在<template>里写内联样式,直接在<style>块中使用var()函数即可绑定:
立即学习“前端免费学习笔记(深入)”;
- 支持
scoped样式,变量仍可穿透生效(因:root和[data-theme]作用于全局) - 可配合
calc()、rgba()等函数组合使用,提升灵活性 - 注意 fallback 值写法:
var(--text-primary, #333),增强容错性
示例:
<style scoped>
.card {
background-color: var(--bg-surface);
color: var(--text-primary);
border: 1px solid var(--border-base);
}
</style>
在Vue逻辑中动态切换主题
切换本质是修改document.documentElement的data-theme属性,触发CSS重计算:
- 推荐在根组件(如
App.vue)的mounted钩子中读取 localStorage 初始化主题 - 提供
toggleTheme方法,统一设置属性并持久化存储 - 避免直接操作
style.setProperty逐个改变量——那样会绕过 CSS 层级,失去主题复用能力
示例逻辑:
methods: {
setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme)
localStorage.setItem('preferred-theme', theme)
},
toggleTheme() {
const current = document.documentElement.getAttribute('data-theme')
this.setTheme(current === 'dark' ? 'light' : 'dark')
}
}
模板调用:
<button @click="toggleTheme">切换主题</button>
补充:适配系统偏好与用户选择优先级
真实项目中需兼顾用户主动选择与系统自动偏好(如 macOS / Windows 的深色模式):
- 初始化时先检查
localStorage,有值则用;否则读取window.matchMedia('(prefers-color-scheme: dark)') - 用户手动切换后,应覆盖系统偏好,即“用户选择 > 系统设置”
- 监听系统变化可选加
matchMedia().addEventListener,但仅作兜底,不替代用户操作
这样既尊重用户意愿,又保持体验连贯性。

















