Blazor中动态切换深色/浅色模式的核心是运行时替换根元素class或link标签,并配合CSS变量统一管理主题色;推荐方式为通过CSS变量定义两套值,用theme-dark/theme-light类切换,辅以localStorage持久化和系统偏好适配。

Blazor 中动态切换深色/浅色模式,核心是**在运行时替换或修改页面的 CSS 类或 link 标签**,并配合 CSS 变量(Custom Properties)统一管理主题色。不依赖 JS Interop 也能实现,但结合少量 JS 能更好处理系统偏好和持久化。
1. 使用 CSS 变量 + 切换根元素 class
这是最推荐、最 Blazor-native 的方式:定义两套 CSS 变量值,通过给 或 添加不同 class(如 theme-dark / theme-light)来触发样式切换。
在 wwwroot/css/app.css 中:
:root {
--bg-color: #ffffff;
--text-color: #333333;
--border-color: #e0e0e0;
}
.theme-dark {
--bg-color: #1e1e1e;
--text-color: #e0e0e0;
--border-color: #444444;
}
body {
background-color: var(--bg-color);
color: var(--text-color);
border-color: var(--border-color);
}
在 App.razor 或布局组件中监听主题状态(例如用 CascadingParameter 或服务),然后设置根元素 class:
立即学习“前端免费学习笔记(深入)”;
- 用
@code块调用JSRuntime.InvokeVoidAsync("document.documentElement.classList.toggle", "theme-dark")切换 class - 更简洁:在
Layout.razor的@onload或生命周期中,根据当前主题调用 JS 设置 class(如document.documentElement.className = 'theme-dark')
2. 动态加载/替换 样式表
适合已有完全独立的 dark.css / light.css 文件的场景。通过 JS 修改 中的 的 href 属性。
MDWechat是一款xposed插件,能够使使微信Material Design化。功能实现的功能有:1.主界面 TabLayout Material 化,支持自定义图标2.主界面 4 个页面背景修改3.全局 ActionBar 和 状态栏 颜色修改,支持主界面和聊天页面的沉浸主题(4.0新增)4.自动识别微信深色模式以调整MDwechat配色方案(3.6新增)5.主界面添加悬浮按钮(Float
步骤:
- 在
wwwroot/index.html中预留一个带 id 的 link 标签: - 在 Blazor 组件中注入
IJSRuntime,切换时调用:await js.InvokeVoidAsync("changeThemeStylesheet", "dark.css") - 对应 JS 函数(放在
wwwroot/js/theme.js,并在 index.html 引入):
window.changeThemeStylesheet = (href) => {
const link = document.getElementById('theme-stylesheet');
link.href = `css/${href}`;
};
3. 持久化与系统偏好适配
用户下次打开仍保持上次选择,且默认跟随系统设置:
- 用
localStorage存储当前主题(如"theme": "dark"),在组件初始化时读取 - 首次加载无本地值时,用
window.matchMedia('(prefers-color-scheme: dark)').matches获取系统偏好 - 监听系统变化(可选):
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ...),自动同步
4. 封装为可复用服务(ThemeService)
创建 ThemeService.cs 管理状态、切换逻辑和 JS 调用:
- 包含
CurrentTheme(enum)、OnThemeChanged事件 - 方法如
SetTheme(ThemeMode mode):更新 localStorage + 触发 JS 切换 + 触发事件 - 在
Program.cs注册为 scoped 服务:builder.Services.AddScoped() - 任意组件注入后即可响应式切换:
@inject ThemeService Theme+@onclick="() => Theme.SetTheme(ThemeMode.Dark)"
基本上就这些。关键不是“换 CSS 文件”,而是用 CSS 变量 + class 控制,轻量、高效、易维护。JS 仅做 DOM 操作辅助,不侵入样式逻辑。









