0

0

使用JavaScript和CSS变量实现动态颜色主题切换

碧海醫心

碧海醫心

发布时间:2025-07-17 19:22:17

|

1045人浏览过

|

来源于php中文网

原创

使用javascript和css变量实现动态颜色主题切换

本文详细介绍了如何利用CSS自定义属性和JavaScript实现网页的明暗模式切换功能。重点阐述了通过JavaScript动态修改CSS变量的原理,并特别强调了在条件判断中正确使用比较运算符(==或===)而非赋值运算符(=)的重要性,以避免常见的逻辑错误,确保主题切换功能的稳定运行。

在现代网页设计中,为用户提供自定义体验,特别是颜色主题切换(如明暗模式),已成为一项普遍需求。这不仅能提升用户体验,还能在不同光照环境下提供更好的可读性。本教程将深入探讨如何结合CSS自定义属性(CSS Variables)和JavaScript来实现一个高效且易于管理的主题切换系统。

1. 核心技术:CSS自定义属性(CSS Variables)

CSS自定义属性(也称为CSS变量)是实现动态主题切换的关键。它们允许我们定义可在整个CSS文档中重复使用的值,并且这些值可以通过JavaScript轻松修改。通过将颜色、字体等主题相关的属性定义为变量,我们可以在运行时动态改变它们,从而实现主题的切换。

在 :root 伪类中定义全局变量是最佳实践,因为 :root 代表文档的根元素(),确保这些变量在整个文档中都可访问。

CSS 代码示例:

立即学习Java免费学习笔记(深入)”;

@import url('https://fonts.googleapis.com/css2?family=Lexend&family=Nunito&display=swap');

/* 定义CSS变量,设置默认(亮色)主题 */
:root {
  --maincolor: #ed1818; /* 主色调 */
  --backgroundcolor: #d4d4d4; /* 页面背景色 */
  --bodycolor: #f2f2f2; /* 内容区域背景色 */
  --fontcolor: black; /* 字体颜色 */
}

/* 应用CSS变量到元素 */
body {
  background-color: var(--backgroundcolor);
  font-family: Nunito, sans-serif;
  color: var(--fontcolor);
  padding: 20px;
}

.body {
  background-color: var(--bodycolor);
  border-radius: 5px;
  padding: 10px 30px;
}

.header {
  padding: 20px 0px;
}

button {
  border: 0px solid black;
  border-radius: 5px;
  background-color: var(--backgroundcolor);
  font-family: Nunito, sans-serif; /* 注意:原文此处有拼写错误,已更正为 font-family */
  color: var(--fontcolor);
  padding: 10px;
  transition-duration: 0.2s; /* 添加过渡效果,使切换更平滑 */
}

button:hover {
  border: 0px solid black;
  border-radius: 5px;
  background-color: var(--bodycolor);
  font-family: Nunito, sans-serif; /* 注意:原文此处有拼写错误,已更正为 font-family */
  color: var(--fontcolor);
  cursor: pointer;
}

2. JavaScript逻辑:实现主题切换

JavaScript负责检测用户操作并动态修改CSS变量的值。我们将创建一个函数,该函数根据当前主题状态切换颜色方案。

HTML 结构示例:

一个简单的HTML结构,包含一个用于触发主题切换的按钮。

@@##@@

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

JavaScript 代码与常见陷阱:

在实现主题切换逻辑时,一个常见的错误是混淆赋值运算符(=)和比较运算符(==或===)。

初始(错误)的JavaScript代码:

var r = document.querySelector(':root');
var isdark = 0; // 0代表亮色模式,1代表暗色模式

function darkLight() {
  if (isdark = 0) { // 错误:这里使用了赋值运算符
    r.style.setProperty('--backgroundcolor', '#1a1a1a');
    r.style.setProperty('--bodycolor', '#3b3b3b')
    r.style.setProperty('--fontcolor', 'white')
    isdark = 1;
  } else if (isdark = 1) { // 错误:这里也使用了赋值运算符
    r.style.setProperty('--backgroundcolor', '#d4d4d4')
    r.style.setProperty('--bodycolor', '#f2f2f2')
    r.style.setProperty('--fontcolor', 'black')
    isdark = 0;
  }
}

问题分析: 上述代码中的 if (isdark = 0) 和 else if (isdark = 1) 是导致按钮在几次点击后失效的根本原因。在JavaScript中:

  • = 是赋值运算符,它将右侧的值赋给左侧的变量,并返回赋的值。
  • == 是相等比较运算符,用于比较两个值是否相等(可能进行类型转换)。
  • === 是严格相等比较运算符,用于比较两个值是否严格相等(不进行类型转换)。

当 if (isdark = 0) 执行时,isdark 会被赋值为 0,然后整个表达式的值就是 0。在JavaScript中,0 被视为 false。因此,无论 isdark 之前的实际值是什么,if (isdark = 0) 永远不会为真,if 块内的代码永远不会执行。同理,else if (isdark = 1) 会将 isdark 赋值为 1,然后表达式的值为 1,1 被视为 true。这意味着 else if 块会一直被执行。结果就是,代码始终停留在亮色模式,并且 isdark 的值在每次点击后都被错误地重置。

Cutout.Pro抠图
Cutout.Pro抠图

AI批量抠图去背景

下载

修正后的JavaScript代码:

为了正确地比较 isdark 的值,我们需要将赋值运算符 = 替换为比较运算符 == 或 ===。

var r = document.querySelector(':root');
var isdark = 0; // 0代表亮色模式,1代表暗色模式

function darkLight() {
  // 获取 :root 元素的样式对象,用于设置CSS变量
  var rootStyle = r.style;

  if (isdark === 0) { // 正确:使用严格相等比较运算符
    // 切换到暗色模式
    rootStyle.setProperty('--backgroundcolor', '#1a1a1a');
    rootStyle.setProperty('--bodycolor', '#3b3b3b');
    rootStyle.setProperty('--fontcolor', 'white');
    isdark = 1; // 更新状态为暗色模式
  } else if (isdark === 1) { // 正确:使用严格相等比较运算符
    // 切换到亮色模式
    rootStyle.setProperty('--backgroundcolor', '#d4d4d4');
    rootStyle.setProperty('--bodycolor', '#f2f2f2');
    rootStyle.setProperty('--fontcolor', 'black');
    isdark = 0; // 更新状态为亮色模式
  }
}

注意: 在HTML中,onclick 属性需要调用函数,所以应该是 onclick="darkLight()",而不是 onclick="darkLight"。原文HTML中SVG图标的 onclick 是正确的,但按钮的 onclick 没有括号,这也会导致问题(尽管不是核心的逻辑错误)。请确保所有调用都包含括号。

3. 增强与优化

为了使主题切换功能更加健壮和用户友好,可以考虑以下优化:

3.1 持久化用户偏好(LocalStorage)

用户通常希望其主题选择在下次访问时得到保留。localStorage 是一个很好的选择,用于在浏览器中存储少量数据。

var r = document.querySelector(':root');
// 尝试从 localStorage 获取用户偏好,如果没有则默认为 0 (亮色)
var isdark = localStorage.getItem('theme') === 'dark' ? 1 : 0;

// 初始化主题(根据存储的偏好)
function applyTheme() {
  if (isdark === 1) {
    r.style.setProperty('--backgroundcolor', '#1a1a1a');
    r.style.setProperty('--bodycolor', '#3b3b3b');
    r.style.setProperty('--fontcolor', 'white');
  } else {
    r.style.setProperty('--backgroundcolor', '#d4d4d4');
    r.style.setProperty('--bodycolor', '#f2f2f2');
    r.style.setProperty('--fontcolor', 'black');
  }
}

// 在页面加载时应用主题
applyTheme();

function darkLight() {
  if (isdark === 0) {
    r.style.setProperty('--backgroundcolor', '#1a1a1a');
    r.style.setProperty('--bodycolor', '#3b3b3b');
    r.style.setProperty('--fontcolor', 'white');
    isdark = 1;
    localStorage.setItem('theme', 'dark'); // 保存用户偏好
  } else {
    r.style.setProperty('--backgroundcolor', '#d4d4d4');
    r.style.setProperty('--bodycolor', '#f2f2f2');
    r.style.setProperty('--fontcolor', 'black');
    isdark = 0;
    localStorage.setItem('theme', 'light'); // 保存用户偏好
  }
}

3.2 响应系统主题(prefers-color-scheme)

现代浏览器支持 prefers-color-scheme 媒体查询,允许网页根据用户的操作系统主题偏好自动调整。

// 检查系统偏好,但用户手动切换的优先级更高
if (localStorage.getItem('theme') === null) {
  if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    isdark = 1; // 系统偏好为暗色
  } else {
    isdark = 0; // 系统偏好为亮色
  }
}
// ... (其余代码同上,确保 applyTheme() 在初始化时被调用)

// 监听系统主题变化(可选)
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
  if (localStorage.getItem('theme') === null) { // 仅在用户未手动设置时响应系统变化
    isdark = event.matches ? 1 : 0;
    applyTheme();
  }
});

3.3 代码结构优化:通过添加/移除CSS类

直接通过 setProperty 修改变量是可行的,但更常见且灵活的方式是利用CSS类。定义两个主题类(例如 light-theme 和 dark-theme),然后通过JavaScript在

元素上切换这些类。

CSS 示例(新增):

/* 默认亮色主题 */
:root {
  --backgroundcolor: #d4d4d4;
  --bodycolor: #f2f2f2;
  --fontcolor: black;
}

/* 暗色主题变量覆盖 */
body.dark-theme {
  --backgroundcolor: #1a1a1a;
  --bodycolor: #3b3b3b;
  --fontcolor: white;
}

JavaScript 示例(优化后):

function darkLight() {
  const body = document.body;
  if (body.classList.contains('dark-theme')) {
    body.classList.remove('dark-theme');
    localStorage.setItem('theme', 'light');
  } else {
    body.classList.add('dark-theme');
    localStorage.setItem('theme', 'dark');
  }
}

// 页面加载时根据存储的偏好或系统偏好设置主题
(function() {
  const savedTheme = localStorage.getItem('theme');
  if (savedTheme) {
    if (savedTheme === 'dark') {
      document.body.classList.add('dark-theme');
    }
  } else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
    document.body.classList.add('dark-theme');
  }
})();

这种方法更简洁,并且将主题的具体颜色值完全保留在CSS中,使得管理更加清晰。

总结

通过本教程,我们学习了如何利用CSS自定义属性和JavaScript构建一个功能完善的网页颜色主题切换系统。核心要点包括:

  1. CSS自定义属性:利用 :root 定义全局变量,简化主题管理。
  2. JavaScript动态控制:使用 element.style.setProperty() 或更优的通过切换CSS类来改变主题。
  3. 精确的条件判断:务必使用 == 或 === 进行比较,避免赋值运算符 = 导致的逻辑错误。
  4. 用户体验优化:结合 localStorage 存储用户偏好,并利用 prefers-color-scheme 响应系统主题。

掌握这些技术,您将能够为用户提供更加个性化和无缝的浏览体验。

YouTube Icon

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1503

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

233

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

783

2023.08.22

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

82

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

96

2025.09.18

C++类型转换方式
C++类型转换方式

本专题整合了C++类型转换相关内容,想了解更多相关内容,请阅读专题下面的文章。

301

2025.07.15

php环境变量如何设置
php环境变量如何设置

本合集详细讲解PHP环境变量的设置方法,涵盖Windows、Linux及常见服务器环境配置技巧,助你快速掌握环境变量的正确配置。阅读专题下面的文章了解更多详细内容。

0

2026.01.31

php图片如何上传
php图片如何上传

本合集涵盖PHP图片上传的核心方法、安全处理及常见问题解决方案,适合初学者与进阶开发者。阅读专题下面的文章了解更多详细内容。

2

2026.01.31

热门下载

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

精品课程

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

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

CSS教程
CSS教程

共754课时 | 25.7万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号