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 修改
中的<link rel="stylesheet">的
href属性。
步骤:
在wwwroot/index.html中预留一个带 id 的 link 标签:
<link id="theme-stylesheet" rel="stylesheet" href="css/light.css">在 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<themeservice>()</themeservice>任意组件注入后即可响应式切换:
@inject ThemeService Theme+
@onclick="() => Theme.SetTheme(ThemeMode.Dark)"
基本上就这些。关键不是“换 CSS 文件”,而是用 CSS 变量 + class 控制,轻量、高效、易维护。JS 仅做 DOM 操作辅助,不侵入样式逻辑。
