我会从最基础、最推荐的方法讲起,再到其他方法,并附上完整的代码示例。
核心思想
无论用哪种方法,JavaScript 切换 CSS 的核心思想都是:通过 JavaScript 找到 HTML 元素,然后修改它的样式属性。
最常用、最灵活、性能也最好的方法是 操作元素的 class 属性,为什么呢?
- 关注点分离:HTML 负责结构,CSS 负责表现,我们不应该在 JavaScript 中写大量的 CSS 代码(
element.style.color = 'red'),而应该通过class来关联 CSS 样式。 - 可维护性:样式定义在 CSS 文件中,修改样式时只需要改动 CSS,而不需要动 JavaScript 代码。
- 复用性:一个
class可以被多个元素使用,也可以在一个元素上组合使用。
操作 Class(最推荐)
这是最专业、最常用的方法,我们预先在 CSS 文件中定义好不同的样式类,然后通过 JavaScript 来添加或移除这些类。
基本步骤
- HTML: 给需要切换样式的元素添加一个共同的
class或id,以便 JavaScript 能够找到它。 - CSS: 定义多个不同的样式类(
.theme-light和.theme-dark)。 - JavaScript: 编写函数,通过
element.classList.add()和element.classList.remove()方法来切换类。
完整示例:一个简单的暗黑/明亮主题切换器
这个例子将展示如何点击一个按钮,在页面的明亮主题和暗黑主题之间切换。
HTML (index.html)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">CSS 主题切换示例</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>我的网站</h1>
<button id="theme-toggle-btn">切换主题</button>
</header>
<main>
<p>点击右上角的按钮,可以切换页面的主题。</p>
<p>这个示例展示了如何使用 JavaScript 来动态地添加或移除 CSS 类,从而改变整个页面的样式。</p>
</main>
<!-- 引入 JavaScript 文件 -->
<script src="script.js"></script>
</body>
</html>
CSS (style.css)
这里我们定义了两个主题:默认的明亮主题(body 的默认样式)和暗黑主题(.dark-theme 类)。
/* --- 明亮主题 (默认) --- */
body {
background-color: #f0f0f0;
color: #333;
font-family: Arial, sans-serif;
transition: background-color 0.3s, color 0.3s; /* 添加过渡效果,使切换更平滑 */
}
header {
background-color: #fff;
padding: 1rem;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
#theme-toggle-btn {
padding: 0.5rem 1rem;
border: 1px solid #ccc;
background-color: #fff;
cursor: pointer;
border-radius: 5px;
}
/* --- 暗黑主题 --- */
/* 当 body 元素有 .dark-theme 这个类时,应用以下样式 */
body.dark-theme {
background-color: #222;
color: #f0f0f0;
}
body.dark-theme header {
background-color: #333;
box-shadow: 0 2px 4px rgba(255,255,255,0.1);
}
body.dark-theme #theme-toggle-btn {
background-color: #444;
border-color: #555;
color: #f0f0f0;
}
JavaScript (script.js)
这是实现切换逻辑的核心,我们使用 classList API。
// 1. 获取需要操作的元素
const body = document.body;
const themeToggleBtn = document.getElementById('theme-toggle-btn');
// 2. 为按钮添加点击事件监听器
themeToggleBtn.addEventListener('click', () => {
// 3. 切换 .dark-theme 类
// classList.toggle() 方法会检查元素是否有指定的类。
// 如果有,就移除它;如果没有,就添加它,非常方便!
body.classList.toggle('dark-theme');
// (可选) 保存用户的选择到 localStorage
// 这样即使用户刷新页面,主题也会被记住
if (body.classList.contains('dark-theme')) {
localStorage.setItem('theme', 'dark');
} else {
localStorage.setItem('theme', 'light');
}
});
// (可选) 页面加载时,从 localStorage 读取并应用之前保存的主题
window.addEventListener('DOMContentLoaded', () => {
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
body.classList.add('dark-theme');
}
});
代码解释:
document.getElementById('theme-toggle-btn'): 获取 ID 为theme-toggle-btn的按钮元素。addEventListener('click', () => { ... }): 为按钮绑定一个点击事件,当用户点击按钮时,执行箭头函数() => { ... }中的代码。body.classList.toggle('dark-theme'): 这是关键的一行代码。classList是一个 DOMTokenList 对象,提供了操作类的方法。toggle()是一个非常有用的方法,它会“切换”指定的类。body当前没有dark-theme这个类,toggle()就会添加它,页面样式变为暗黑主题。body当前已经有dark-theme这个类,toggle()就会移除它,页面样式变回明亮主题。
localStorage: 这是一个浏览器提供的 API,可以在用户的浏览器中持久化存储数据(即使关闭浏览器后数据也不会丢失),我们用它来记住用户选择的主题,这样下次访问网站时,主题设置仍然有效。
直接操作 Style 属性
这种方法不推荐用于复杂的样式切换,但适用于需要动态计算或修改单个简单样式值的场景。
基本语法
element.style.propertyName = 'value';
示例:改变单个元素的颜色
假设我们只想把标题 h1 的颜色变成蓝色。
HTML:
<h1 id="my-title">这是一个标题</h1> <button id="color-btn">变蓝</button>
JavaScript:
const myTitle = document.getElementById('my-title');
const colorBtn = document.getElementById('color-btn');
colorBtn.addEventListener('click', () => {
// 直接修改 style 属性
myTitle.style.color = 'blue';
myTitle.style.fontSize = '2em'; // 也可以同时修改多个
});
缺点:
- 样式内联:CSS 代码直接写在 JavaScript 里,破坏了关注点分离的原则。
- 无法使用伪类或复杂选择器:比如你无法通过
element.style :hover { ... }来修改悬停效果。 - 优先级问题:直接设置的
style优先级很高,可能会覆盖掉 CSS 文件中的样式。
动态创建或修改 <style>
这种方法比较“暴力”,通常用于需要动态生成大量 CSS 规则的场景,比如创建复杂的主题系统或图表样式。
示例:动态创建一个新的 <style>
// 创建一个新的 <style> 元素
const style = document.createElement('style');
style.innerHTML = `
body {
background-color: purple !important;
color: yellow !important;
}
`;
// 将这个 <style> 标签添加到 <head> 中
document.head.appendChild(style);
// 如果想移除,可以这样:
// document.head.removeChild(style);
注意:使用 !important 是为了确保动态添加的样式能够覆盖掉原有的样式,这种方法应该谨慎使用,因为它可能会影响其他组件的样式。
总结与对比
方法
优点
缺点
适用场景
操作 Class (推荐)
关注点分离、代码清晰、易于维护、性能好、可复用
需要预先在 CSS 中定义好类
绝大多数场景,特别是主题切换、组件状态切换等。
操作 Style 属性
简单直接,适合快速修改少量样式
样式内联、难以维护、无法使用复杂选择器
动态计算单个值,如根据窗口大小调整元素宽度、颜色等。
操作 <style>
动态生成
这种方法比较“暴力”,通常用于需要动态生成大量 CSS 规则的场景,比如创建复杂的主题系统或图表样式。
示例:动态创建一个新的 <style>
// 创建一个新的 <style> 元素
const style = document.createElement('style');
style.innerHTML = `
body {
background-color: purple !important;
color: yellow !important;
}
`;
// 将这个 <style> 标签添加到 <head> 中
document.head.appendChild(style);
// 如果想移除,可以这样:
// document.head.removeChild(style);
注意:使用 !important 是为了确保动态添加的样式能够覆盖掉原有的样式,这种方法应该谨慎使用,因为它可能会影响其他组件的样式。
总结与对比
方法
优点
缺点
适用场景
操作 Class (推荐)
关注点分离、代码清晰、易于维护、性能好、可复用
需要预先在 CSS 中定义好类
绝大多数场景,特别是主题切换、组件状态切换等。
操作 Style 属性
简单直接,适合快速修改少量样式
样式内联、难以维护、无法使用复杂选择器
动态计算单个值,如根据窗口大小调整元素宽度、颜色等。
操作 <style>
动态生成
// 创建一个新的 <style> 元素
const style = document.createElement('style');
style.innerHTML = `
body {
background-color: purple !important;
color: yellow !important;
}
`;
// 将这个 <style> 标签添加到 <head> 中
document.head.appendChild(style);
// 如果想移除,可以这样:
// document.head.removeChild(style);
注意:使用 !important 是为了确保动态添加的样式能够覆盖掉原有的样式,这种方法应该谨慎使用,因为它可能会影响其他组件的样式。
总结与对比
| 方法 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 操作 Class (推荐) | 关注点分离、代码清晰、易于维护、性能好、可复用 | 需要预先在 CSS 中定义好类 | 绝大多数场景,特别是主题切换、组件状态切换等。 |
| 操作 Style 属性 | 简单直接,适合快速修改少量样式 | 样式内联、难以维护、无法使用复杂选择器 | 动态计算单个值,如根据窗口大小调整元素宽度、颜色等。 |
操作 <style> |
动态生成 |
