讲师中心 微信公众号
AI工具推荐 视频效率加速

实现可持久化的暗黑模式切换:同时控制背景、文本与特定元素边框样式

冬墨同学_1404

冬墨同学_1404

发布时间:2025-11-23 14:17:36

|

256人浏览过

|

来源于php中文网

原创

实现可持久化的暗黑模式切换:同时控制背景、文本与特定元素边框样式

本教程详细阐述如何使用javascript和css实现一个功能完善的暗黑模式切换器。我们将学习如何动态改变页面背景色、文本颜色,并解决特定元素(如带有.veritas类的div)的border-bottom颜色同步切换问题。教程还涵盖了利用localstorage实现用户偏好持久化的方法,确保模式选择在页面刷新后依然有效。

引言:构建用户友好的暗黑模式切换功能

暗黑模式(Dark Mode)已成为现代Web应用中一项备受欢迎的功能,它不仅能减少夜间使用时的视觉疲劳,还能在OLED屏幕上节省电量。实现暗黑模式通常涉及动态切换页面的背景色、文本颜色以及其他UI元素的样式。本教程将深入探讨如何利用JavaScript和CSS构建一个健壮的暗黑模式切换器,特别关注如何同步更改特定元素的边框颜色,并利用localStorage实现用户偏好的持久化。

核心技术栈

在开始构建之前,我们先了解所使用的核心技术:

  • HTML: 用于定义页面结构和交互元素,如按钮和内容容器。
  • CSS: 用于定义元素的基础样式、暗黑模式下的特定样式,以及实现平滑的过渡效果。
  • JavaScript: 作为核心逻辑层,负责监听用户事件、操作DOM元素样式、管理CSS类以及处理localStorage进行状态持久化。

HTML 结构

首先,我们需要一个按钮来触发模式切换,以及一个带有特定类名(例如.veritas)的div元素,其底部边框颜色将随模式切换而改变。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>暗黑模式切换教程</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <button id="toggleBtn">切换模式</button>
    <div class="veritas">
        <p>这是一个示例内容,其底部边框颜色将随模式切换而改变。</p>
        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Adipisci, molestias!</p>
    </div>

    <script src="script.js"></script>
</body>
</html>

CSS 样式定义

CSS部分负责定义页面的基础外观、暗黑模式下的样式,以及为模式切换添加平滑的过渡效果,以提升用户体验。

/* style.css */
body {
    margin: 0;
    padding: 20px;
    min-height: 100vh; /* 确保body至少占满视口高度 */
    background-color: #FFFFFF; /* 默认亮色背景 */
    color: #101010; /* 默认亮色文本 */
    font-family: Arial, sans-serif;
    transition: background-color 0.3s ease, color 0.3s ease; /* 为背景和文本颜色添加过渡 */
}

/* 暗黑模式样式 */
body.dark-mode {
    background-color: #101010;
    color: #FFFFFF;
}

/* 切换按钮样式 */
#toggleBtn {
    padding: 10px 15px;
    margin-bottom: 20px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    background-color: #007bff;
    color: white;
    font-size: 16px;
    transition: background-color 0.3s ease;
}

#toggleBtn:hover {
    background-color: #0056b3;
}

/* veritas div 样式 */
.veritas {
    width: 90%;
    max-width: 800px;
    margin: 20px auto; /* 居中显示 */
    padding: 20px;
    border: 1px solid #CCCCCC; /* 默认边框,可根据需要调整 */
    border-bottom: 1px solid #101010; /* 初始底部边框颜色 */
    background-color: #F8F8F8; /* 亮色模式下的背景 */
    border-radius: 8px;
    box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    transition: border-bottom-color 0.3s ease, background-color 0.3s ease, border-color 0.3s ease; /* 为边框颜色和背景色添加过渡 */
}

/* 暗黑模式下 .veritas 的特定样式 */
body.dark-mode .veritas {
    background-color: #222222; /* 暗黑模式下的背景 */
    border-color: #444444; /* 暗黑模式下的普通边框 */
}

关键点:

  • body和.veritas元素都添加了transition属性,确保样式切换时有平滑的动画效果。
  • .veritas的border-bottom属性在CSS中设置了初始值,JavaScript将动态修改其颜色。

JavaScript 逻辑实现

JavaScript是实现动态切换的核心。它负责获取DOM元素、监听用户点击事件、根据当前模式应用不同的样式,并将用户偏好保存到localStorage中。

java-api-doc-generator
java-api-doc-generator

分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。

下载

问题分析与修正

在原始代码中,存在两个主要问题导致border-bottom颜色未能正确切换:

  1. 元素选择错误: document.getElementById(".veritas") 试图通过ID选择器获取类名为.veritas的元素。getElementById只接受元素的ID作为参数,而不是类选择器。对于类名选择,应使用document.getElementsByClassName("veritas")。需要注意的是,getElementsByClassName返回的是一个HTMLCollection(类似数组),即使只有一个元素,也需要通过索引(例如[0])来访问它。
  2. 样式属性设置错误: borderBottom.style.borderBottom = borderBottom; 这行代码试图将一个颜色值直接赋给borderBottom这个复合CSS属性。borderBottom是一个简写属性,它包含了border-bottom-width、border-bottom-style和border-bottom-color。要单独设置底部边框的颜色,应该使用borderBottomColor属性。

完整的 JavaScript 代码

// script.js

// 1. 获取DOM元素
const toggleBtn = document.getElementById("toggleBtn");
const body = document.getElementsByTagName("body")[0];
// 修正:使用 getElementsByClassName 获取类名为"veritas"的元素
const veritasDiv = document.getElementsByClassName("veritas")[0]; // 注意 [0] 因为它返回一个HTMLCollection

// 2. 定义主题切换函数
// isDarkMode参数为true表示切换到暗黑模式,false表示切换到亮色模式
function applyTheme(isDarkMode) {
    let bgColor, textColor, veritasBorderColor, buttonText;

    if (isDarkMode) {
        body.classList.add("dark-mode"); // 添加暗黑模式类
        bgColor = "#101010"; // 暗黑模式背景色
        textColor = "#FFFFFF"; // 暗黑模式文本色
        veritasBorderColor = "#FFFFFF"; // 暗黑模式下.veritas的底部边框色
        buttonText = "Dark mode is off"; // 按钮文本
    } else {
        body.classList.remove("dark-mode"); // 移除暗黑模式类
        bgColor = "#FFFFFF"; // 亮色模式背景色
        textColor = "#101010"; // 亮色模式文本色
        veritasBorderColor = "#101010"; // 亮色模式下.veritas的底部边框色
        buttonText = "Dark mode is on"; // 按钮文本
    }

    // 应用样式到body
    body.style.backgroundColor = bgColor;
    body.style.color = textColor;

    // 修正:直接设置veritasDiv的borderBottomColor属性
    if (veritasDiv) { // 确保元素存在,避免空指针错误
        veritasDiv.style.borderBottomColor = veritasBorderColor;
    }

    // 更新按钮文本
    toggleBtn.textContent = buttonText;

    // 保存主题偏好到 localStorage
    localStorage.setItem("theme", isDarkMode ? "dark" : "light");
}

// 3. 页面加载时,从 localStorage 读取并应用主题
document.addEventListener("DOMContentLoaded", () => {
    const savedTheme = localStorage.getItem("theme");
    // 检查用户系统是否偏好暗色模式(仅在没有保存主题时考虑)
    const prefersDarkScheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;

    if (savedTheme) {
        // 如果 localStorage 中有保存的主题,则应用它
        applyTheme(savedTheme === "dark");
    } else if (prefersDarkScheme) {
        // 如果没有保存主题,但系统偏好暗色模式,则应用暗色模式
        applyTheme(true);
    } else {
        // 否则,默认应用亮色模式
        applyTheme(false);
    }
});

// 4. 按钮点击事件监听
toggleBtn.addEventListener("click", () => {
    // 判断当前是否为暗黑模式
    const isCurrentlyDarkMode = body.classList.contains("dark-mode");
    // 切换到相反的模式
    applyTheme(!isCurrentlyDarkMode);
});

代码解析:

  1. 元素获取:
    • document.getElementById("toggleBtn") 获取切换按钮。
    • document.getElementsByTagName("body")[0] 获取body元素。
    • document.getElementsByClassName("veritas")[0] 正确获取了第一个(也是唯一的)类名为veritas的div元素。
  2. applyTheme 函数: 这是一个核心函数,封装了应用主题的所有逻辑。它接受一个布尔值isDarkMode,根据其值来设置背景色、文本色、特定边框色和按钮文本。
    • 通过body.classList.add/remove("dark-mode")来切换body元素的CSS类,从而利用CSS预定义的暗黑模式样式。
    • 直接修改body.style.backgroundColor和body.style.color来覆盖或补充CSS样式。
    • 修正后的关键点: veritasDiv.style.borderBottomColor = veritasBorderColor; 正确地设置了底部边框的颜色。
    • localStorage.setItem("theme", ...) 用于将当前主题状态保存到浏览器本地存储,以便用户下次访问时能记住偏好。
  3. 页面加载时的处理 (DOMContentLoaded):
    • 当页面完全加载后,首先检查localStorage中是否有保存的主题偏好。
    • 如果存在,则直接应用该偏好。
    • 如果不存在,则检查用户操作系统的暗色模式偏好 (window.matchMedia('(prefers-color-scheme: dark)'))。这是一个现代浏览器API,允许网站根据用户系统设置自动调整主题。
    • 如果以上两者都没有,则默认应用亮色模式。
  4. 按钮点击事件:
    • 当toggleBtn被点击时,它会检测body当前是否包含dark-mode类,然后调用applyTheme函数,传入当前模式的反向值,实现模式切换。

注意事项与最佳实践

  • 平滑过渡: 在CSS中为background-color, color, border-bottom-color等属性添加transition,可以使模式切换过程更加平滑,提升用户体验。

  • CSS 变量 (推荐): 对于更复杂的应用,建议使用CSS变量(Custom Properties)来管理主题颜色。这样可以减少JavaScript直接操作style属性的次数,只需通过JavaScript切换一个CSS类,然后CSS变量会自动更新。

    :root { /* 亮色模式默认值 */
      --bg-color: #FFFFFF;
      --text-color: #101010;
      --veritas-border-bottom-color: #101010;
    }
    
    .dark-mode {
      --bg-color: #101010;
      --text-color: #FFFFFF;
      --veritas-border-bottom-color: #FFFFFF;
    }
    
    body {
      background-color: var(--bg-color);
      color: var(--text-color);
      transition: background-color 0.3s ease, color 0.3s ease;
    }
    
    .veritas {
      border-bottom-color: var(--veritas-border-bottom-color);
      transition: border-bottom-color 0.3s ease;
    }

    在这种情况下,JavaScript只需切换body上的dark-mode类,而无需直接修改style属性。

  • 容错处理: 在JavaScript中操作DOM元素之前,最好检查元素是否存在(例如if (veritasDiv)),以避免在某些情况下(如元素未加载或被移除)出现运行时错误。

总结

通过本教程,我们学习了如何构建一个功能完善且用户友好的暗黑模式切换器。关键在于:

  1. 正确的DOM元素选择: 使用document.getElementsByClassName代替getElementById来获取类名元素,并注意其返回的是HTMLCollection。
  2. 精确的样式属性操作: 针对复合CSS属性(如border-bottom),应使用更具体的属性(如borderBottomColor)来设置单个样式值。
  3. 利用localStorage实现持久化: 确保用户的模式选择在页面刷新后依然有效,提升用户体验。
  4. 结合CSS过渡: 为样式变化添加平滑动画,使切换过程更自然。

掌握这些技术,您可以轻松为您的Web应用添加强大的主题切换功能。

热门AI工具

更多
创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

6407

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2688

2023.08.10

DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

6541

2024.08.14

html边框设置教程
html边框设置教程

本教程将带你全面掌握HTML/CSS边框设置,从基础的border属性讲起,涵盖所有边框样式、圆角设置及高级技巧,帮助你快速上手实现各种边框效果。

2833

2025.09.02

css3transition
css3transition

css3transition属性用于指定如何从一个CSS样式过渡到另一个CSS样式,本专题为大家提供transition相关的文章、相关下载和相关课程,大家可以免费体验。

1970

2023.06.27

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

100

2026.10.28

Vite 如何搭配 Vue.js
Vite 如何搭配 Vue.js

Vite搭配Vue.js专题汇集创建Vue 3项目、配置开发环境、路径别名、Vue插件、代理、多环境构建与调试的已审核文章,帮助读者完成从初始化到日常开发的配置。

60

2026.10.28

Vite 项目目录怎么看
Vite 项目目录怎么看

Vite项目目录专题汇集入口文件、src源码、public静态资源、路径别名、项目根目录和构建输出目录相关的已审核文章,帮助读者理解各文件夹的用途与引用方式。

220

2026.10.28

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

140

2026.10.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 1.6万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 6.1万人学习

CSS教程
CSS教程

共754课时 | 99.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn