Blazor 如何实现动态切换 CSS 实现深色/浅色模式

来源:安卓APP网作者:印尼程序员头衔:程序员
导读:本期聚焦于小伙伴创作的《Blazor 如何实现动态切换 CSS 实现深色/浅色模式》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Blazor 如何实现动态切换 CSS 实现深色/浅色模式》有用,将其分享出去将是对创作者最好的鼓励。

在Blazor应用开发中,动态切换CSS实现深色和浅色模式是提升用户使用体验的重要功能,用户可以根据自己的使用场景选择更舒适的界面主题,避免强光下看不清内容或者暗环境下界面过亮刺眼的问题。

Blazor 如何实现动态切换 CSS 实现深色/浅色模式

实现原理概述

实现深色/浅色模式的核心思路是定义两套不同主题的CSS样式,再通过Blazor的逻辑控制当前生效的样式。常见的方式有两种,一种是通过CSS变量定义不同主题的颜色值,切换时修改根节点的变量值;另一种是为不同主题准备独立的CSS文件,动态切换页面引入的CSS文件地址。

方案一:基于CSS变量的实现方式

1. 定义CSS变量

首先在项目的wwwroot/css/app.css文件中定义两套主题的变量,根节点默认使用浅色主题的变量:

/* 浅色主题变量 */
:root {
    --primary-bg-color: #ffffff;
    --primary-text-color: #333333;
    --secondary-bg-color: #f5f5f5;
    --border-color: #e0e0e0;
}

/* 深色主题变量 */
[data-theme="dark"] {
    --primary-bg-color: #1a1a1a;
    --primary-text-color: #e0e0e0;
    --secondary-bg-color: #2d2d2d;
    --border-color: #444444;
}

2. 编写基础页面样式

页面中的样式统一使用定义好的CSS变量,而不是直接写固定颜色值:

.page-container {
    background-color: var(--primary-bg-color);
    color: var(--primary-text-color);
    min-height: 100vh;
    padding: 20px;
}

.card {
    background-color: var(--secondary-bg-color);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 16px;
    margin-bottom: 16px;
}

3. Blazor组件实现切换逻辑

创建一个主题切换组件,管理当前主题状态,修改根节点的data-theme属性来切换CSS变量:

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div class="theme-switch-container">
    <button @onclick="SwitchToLight" class="@(CurrentTheme == "light" ? "active" : "")">浅色模式</button>
    <button @onclick="SwitchToDark" class="@(CurrentTheme == "dark" ? "active" : "")">深色模式</button>
</div>

@code {
    [Parameter]
    public string CurrentTheme { get; set; } = "light";

    [Parameter]
    public EventCallback<string> OnThemeChanged { get; set; }

    private async Task SwitchToLight()
    {
        CurrentTheme = "light";
        await JSRuntime.InvokeVoidAsync("setThemeAttribute", "light");
        await OnThemeChanged.InvokeAsync(CurrentTheme);
    }

    private async Task SwitchToDark()
    {
        CurrentTheme = "dark";
        await JSRuntime.InvokeVoidAsync("setThemeAttribute", "dark");
        await OnThemeChanged.InvokeAsync(CurrentTheme);
    }
}

4. 添加JS互操作代码

wwwroot/js/app.js中添加修改根节点属性的JS方法:

function setThemeAttribute(theme) {
    document.documentElement.setAttribute("data-theme", theme);
    // 持久化主题到本地存储
    localStorage.setItem("app-theme", theme);
}

// 初始化时读取本地存储的主题
function getInitTheme() {
    return localStorage.getItem("app-theme") || "light";
}

5. 主布局中引入组件

MainLayout.razor中引入主题切换组件,初始化时读取本地存储的主题:

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<div class="page-container">
    <ThemeSwitchComponent @ref="themeComponent" OnThemeChanged="HandleThemeChanged" />
    @Body
</div>

@code {
    private ThemeSwitchComponent themeComponent;

    protected override async Task OnInitializedAsync()
    {
        var initTheme = await JSRuntime.InvokeAsync<string>("getInitTheme");
        await JSRuntime.InvokeVoidAsync("setThemeAttribute", initTheme);
    }

    private void HandleThemeChanged(string theme)
    {
        // 可以在这里处理主题切换后的额外逻辑
    }
}

方案二:动态切换CSS文件实现

1. 准备两套独立CSS文件

wwwroot/css目录下创建light-theme.cssdark-theme.css,分别编写两套主题的完整样式:

/* light-theme.css 内容 */
.page-container {
    background-color: #ffffff;
    color: #333333;
}

.card {
    background-color: #f5f5f5;
    border: 1px solid #e0e0e0;
}
/* dark-theme.css 内容 */
.page-container {
    background-color: #1a1a1a;
    color: #e0e0e0;
}

.card {
    background-color: #2d2d2d;
    border: 1px solid #444444;
}

2. 动态修改CSS引入地址

index.html(Blazor WebAssembly)或者_Host.cshtml(Blazor Server)中,给CSS引入标签添加id:

<link id="theme-css" rel="stylesheet" href="css/light-theme.css" />

然后在Blazor组件中通过JS互操作修改这个link标签的href属性:

@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime

<button @onclick="ChangeToDark">切换深色模式</button>
<button @onclick="ChangeToLight">切换浅色模式</button>

@code {
    private async Task ChangeToDark()
    {
        await JSRuntime.InvokeVoidAsync("changeCssFile", "css/dark-theme.css");
        localStorage.setItem("app-theme", "dark");
    }

    private async Task ChangeToLight()
    {
        await JSRuntime.InvokeVoidAsync("changeCssFile", "css/light-theme.css");
        localStorage.setItem("app-theme", "light");
    }
}

对应的JS方法:

function changeCssFile(cssPath) {
    const link = document.getElementById("theme-css");
    if (link) {
        link.href = cssPath;
    }
}

两种方案对比

对比项CSS变量方案动态切换CSS文件方案
实现复杂度较低,只需维护一套CSS文件较高,需要维护两套独立的CSS文件
切换流畅度高,无需重新加载CSS文件稍低,需要加载新的CSS文件
样式隔离性一般,变量全局生效好,两套样式完全独立
适用场景主题差异较小,仅颜色等基础样式不同主题差异较大,布局或组件样式也有区别

扩展功能实现

监听系统主题变化

可以通过JS监听系统的主题偏好变化,自动同步应用主题:

function listenSystemTheme() {
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    mediaQuery.addEventListener("change", (e) => {
        const newTheme = e.matches ? "dark" : "light";
        setThemeAttribute(newTheme);
        // 通知Blazor组件主题变化
        if (window.dotnetHelper) {
            window.dotnetHelper.invokeMethodAsync("HandleSystemThemeChange", newTheme);
        }
    });
}

在Blazor组件中注册dotnetHelper,处理系统主题变化事件即可。

主题状态持久化

前面已经通过localStorage存储了用户选择的主題,下次打开应用时自动读取存储的主题,不需要用户重新选择,提升使用体验。

注意:如果需要支持服务端预渲染,需要在服务端也读取主题状态,避免页面加载时出现主题闪烁的问题,可以在服务端通过cookie存储主题状态,预渲染时优先使用cookie中的主题值。

Blazor深色模式浅色模式动态切换_CSS修改时间:2026-07-13 19:42:38

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。