You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI Blazor Hybrid CSS明暗主题切换失效求解决方案

.NET MAUI Blazor Hybrid 纯CSS明暗主题切换方案

方案一:CSS变量+根类切换(推荐)

这种方式无需动态加载CSS文件,通过定义全局CSS变量,切换根元素类名实现主题切换,更简洁且性能更优。

1. 定义全局CSS变量

在wwwroot/css/app.css中编写基础样式与主题变量:

/* 基础变量(浅色主题) */
:root {
  --bg-primary: #ffffff;
  --text-primary: #1a1a1a;
  --border-color: #e0e0e0;
  --accent-color: #0078d4;
}

/* 深色主题变量覆盖 */
.dark {
  --bg-primary: #1a1a1a;
  --text-primary: #ffffff;
  --border-color: #333333;
  --accent-color: #4ca1ff;
}

/* 全局元素应用变量 */
body {
  background-color: var(--bg-primary);
  color: var(--text-primary);
  transition: background-color 0.3s, color 0.3s;
  margin: 0;
  padding: 0;
}

/* 示例组件样式 */
.card {
  background-color: var(--bg-primary);
  border: 1px solid var(--border-color);
  padding: 1rem;
  border-radius: 8px;
}

.btn {
  background-color: var(--accent-color);
  color: white;
  border: none;
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
}

2. 在布局中控制主题类

修改MainLayout.razor,通过JS操作body类名实现切换,并支持本地存储记忆:

@inherits LayoutComponentBase
@inject IJSRuntime JSRuntime

<!-- 主题切换按钮 -->
<button @onclick="ToggleTheme" class="btn">
    @(IsDark ? "切换到浅色主题" : "切换到深色主题")
</button>

<div class="page-content">
    @Body
</div>

@code {
    private bool IsDark { get; set; }

    protected override async Task OnInitializedAsync()
    {
        // 读取本地存储的主题偏好,无则跟随系统
        var savedTheme = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "theme");
        var prefersDark = await JSRuntime.InvokeAsync<bool>("window.matchMedia('(prefers-color-scheme: dark)').matches");
        
        IsDark = savedTheme == "dark" || (savedTheme == null && prefersDark);
        await UpdateBodyThemeClass();
    }

    private async Task ToggleTheme()
    {
        IsDark = !IsDark;
        await UpdateBodyThemeClass();
        await JSRuntime.InvokeVoidAsync("localStorage.setItem", "theme", IsDark ? "dark" : "light");
    }

    private async Task UpdateBodyThemeClass()
    {
        if (IsDark)
            await JSRuntime.InvokeVoidAsync("document.body.classList.add", "dark");
        else
            await JSRuntime.InvokeVoidAsync("document.body.classList.remove", "dark");
    }
}

方案二:动态加载CSS文件(修复原方案问题)

若坚持使用独立的明暗主题CSS文件,可通过JS直接操作DOM实现动态替换,避免Blazor HeadContent的渲染问题。

1. 准备独立主题CSS文件

创建wwwroot/css/lightMode.css和wwwroot/css/darkMode.css,分别编写对应主题的样式。

2. 编写JS辅助函数

在wwwroot/js/theme-utils.js中添加操作CSS链接的函数:

// 移除现有主题CSS
function removeThemeLink() {
    const themeLink = document.querySelector('link[data-theme="dynamic"]');
    if (themeLink) themeLink.remove();
}

// 添加新主题CSS
function addThemeLink(cssPath) {
    removeThemeLink();
    const link = document.createElement('link');
    link.rel = 'stylesheet';
    link.href = cssPath;
    link.setAttribute('data-theme', 'dynamic');
    document.head.appendChild(link);
}

在index.html中引入该JS:

<script src="js/theme-utils.js"></script>

3. 在布局中调用JS切换

修改MainLayout.razor:

@inherits LayoutComponentBase
@inject IJSRuntime JSRuntime

<button @onclick="ToggleTheme" class="btn">切换主题</button>

@Body

@code {
    private bool IsDark { get; set; }

    protected override async Task OnInitializedAsync()
    {
        var savedTheme = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "theme");
        IsDark = savedTheme == "dark";
        await LoadTheme(IsDark);
    }

    private async Task ToggleTheme()
    {
        IsDark = !IsDark;
        await LoadTheme(IsDark);
        await JSRuntime.InvokeVoidAsync("localStorage.setItem", "theme", IsDark ? "dark" : "light");
    }

    private async Task LoadTheme(bool isDark)
    {
        var cssPath = isDark ? "css/darkMode.css" : "css/lightMode.css";
        await JSRuntime.InvokeVoidAsync("addThemeLink", cssPath);
    }
}

原方案失效原因说明

.NET MAUI Blazor Hybrid的HeadContent组件在WebView环境下,无法像Blazor WebAssembly那样可靠地将内容注入到index.html的<head>标签中,直接通过JS操作DOM是更稳定的替代方式。

内容的提问来源于stack exchange,提问作者Davrozz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:50:35