JavaScript DOM操作实例:怎么获取元素并修改样式
详细讲解 JavaScript DOM 操作的核心步骤:如何使用 querySelector 与 getElementById 精准定位页面元素,以及使用 style 对象与 classList 修改样式的具体方法、代码实例与注意事项。
在网页交互开发中,根据用户行为动态改变页面外观是最基础也是最频繁的任务。完成这一操作的核心逻辑非常明确:先在文档对象模型(DOM)中精准找到目标 HTML 元素,再通过 JavaScript 提供的样式接口对其视觉属性进行改写。掌握这一链路,就能实现从按钮状态切换、弹窗显隐到复杂主题定制的所有动态视觉效果。
一、DOM 获取与样式修改的标准流程
JavaScript 与 HTML 页面交互的桥梁是 DOM。当浏览器解析 HTML 文档时,会将每个标签解析成一个对应的内存节点对象。我们在脚本中修改样式,本质上就是先定位到该节点对象的引用,然后更改其附带的样式属性或 CSS 类名,浏览器在接收到属性变化后重新计算图层并刷新渲染结果。
看一个能够直接运行的微型示例:页面上有一个提示框和一个按钮,点击按钮后将提示框文字颜色变为深蓝色、背景变为浅灰蓝:
<!-- HTML 结构 -->
<div id="status-card" class="card">任务正在排队中...</div>
<button id="update-btn">更新状态</button>
<script>
// 1. 获取元素
const card = document.getElementById('status-card');
const btn = document.getElementById('update-btn');
// 2. 绑定交互并修改样式
btn.addEventListener('click', function () {
if (card) {
card.style.color = '#477DAD';
card.style.backgroundColor = '#F8F9FA';
card.style.border = '1px solid #4F6272';
card.textContent = '任务已顺利完成!';
}
});
</script>
二、精准定位目标元素:常用获取方法与选用策略
修改样式的前提是准确命中节点。现代浏览器提供了多种 DOM 查询 API,不同方法在语法灵活性和返回值类型上存在明确区别。
1. document.querySelector 与 document.querySelectorAll
这是现代前端开发中使用频次最高的方法。它们接受符合 CSS 选择器规范的字符串作为参数:
document.querySelector(selectors):返回文档中匹配指定选择器的第一个元素。未找到时返回null。document.querySelectorAll(selectors):返回匹配指定选择器的所有元素集合(NodeList)。未找到时返回空 NodeList。
// 获取 class 为 .card-title 的单个元素
const title = document.querySelector('.card-title');
// 获取 data-status 属性为 "active" 的列表项
const activeItem = document.querySelector('li[data-status="active"]');
// 获取页面中所有的按钮
const buttons = document.querySelectorAll('.action-panel button');
buttons.forEach(button => {
button.style.cursor = 'pointer';
});
2. document.getElementById
如果目标元素拥有唯一的 id 属性,直接调用 document.getElementById('id值') 是最简单直观的选择。需要特别注意的是,该方法的入参是纯 ID 字符串,不要携带 CSS 选择器的 # 符号。
querySelector 和 getElementById 均返回 null。在直接调用 el.style.xxx 前,务必先进行非空判定或使用现代 JavaScript 的可选链操作符(el?.style),以防止抛出 TypeError: Cannot read properties of null。
三、修改样式的三种主要方式
在成功拿到节点对象后,修改元素样式主要有三种途径。选择哪一种取决于你的样式是预先可预测的,还是需要根据运行时逻辑动态计算。
方式一:操作 classList(行业推荐最佳实践)
将样式细节放在外部或全局 CSS 中,JavaScript 仅负责增删类名,这是维护性最高的方式。element.classList 提供了直观的方法集合:
classList.add('class-name'):添加一个类名。classList.remove('class-name'):移除一个类名。classList.toggle('class-name'):若存在则移除,若不存在则添加,常用于折叠面板、开关按钮。classList.contains('class-name'):检查是否包含某个类名,返回布尔值。classList.replace('old-class', 'new-class'):将已有类名直接替换为新类名。
// 为提示框切换激活与警告状态
const alertBox = document.querySelector('.alert-box');
if (alertBox) {
// 移除普通信息类,加入警告高亮类
alertBox.classList.remove('alert-info');
alertBox.classList.add('alert-warning');
// 一键切换可见状态
alertBox.classList.toggle('is-hidden');
}
方式二:直接操作 element.style 对象
当样式的数值依赖于 JavaScript 计算所得(例如鼠标跟随坐标、拖拽滑块位置、窗口尺寸自适应宽度)时,通过 element.style 直接赋值是最直接的手段。
需要牢记:CSS 中的连字符(kebab-case)命名属性,在 style 对象中全部转为小驼峰命名(camelCase);同时,除数值为 0 外,涉及长度单位的属性必须显式拼接单位(如 px、%、rem):
| CSS 原始属性名 | JavaScript style 属性名 | 标准赋值示例 |
|---|---|---|
background-color |
style.backgroundColor |
el.style.backgroundColor = '#F8F9FA'; |
font-size |
style.fontSize |
el.style.fontSize = '16px'; |
border-radius |
style.borderRadius |
el.style.borderRadius = '8px'; |
z-index |
style.zIndex |
el.style.zIndex = '100'; |
margin-top |
style.marginTop |
el.style.marginTop = '24px'; |
// 动态计算元素位置与透明度
const popup = document.querySelector('#floating-dialog');
if (popup) {
const clientX = 120;
const clientY = 240;
popup.style.position = 'absolute';
popup.style.left = `${clientX}px`;
popup.style.top = `${clientY}px`;
popup.style.opacity = '0.95';
}
方式三:使用 setProperty 与 cssText
常规的 element.style.color = 'red' 无法直接设置 !important 标志,也无法直接操作 CSS 自定义属性(CSS 变量)。遇到这些场景,可以使用 setProperty:
const box = document.querySelector('.theme-box');
if (box) {
// 设置带 !important 权重的属性
box.style.setProperty('color', '#477DAD', 'important');
// 修改 CSS 变量(CSS Custom Properties)
box.style.setProperty('--primary-theme-color', '#4F6272');
// 批量重写内联样式(覆盖之前的整个内联声明)
box.style.cssText = 'color: #2C3E50; background-color: #F8F9FA; padding: 12px;';
}
四、避坑指南与最佳实践检查清单
在实际编码中,修改样式看似简单,但如果不注意执行时机与渲染机制,容易遇到获取不到元素、样式被意外覆盖或页面掉帧卡顿等问题。
1. 确保在 DOM 加载完成后执行查询
如果将 <script> 放在 <head> 中且未加异步标记,浏览器在解析到脚本时 HTML 节点尚未生成,document.querySelector 将直接返回 null。推荐有两种解决方式:
- 将
<script>标签放置在</body>闭合标签之前; - 或者使用
DOMContentLoaded事件包裹逻辑:
document.addEventListener('DOMContentLoaded', function () {
const target = document.querySelector('#my-element');
if (target) {
target.style.display = 'block';
}
});
2. 注意 style 读取与 getComputedStyle 的区别
很多开发者会遇到一个困惑:在外部 CSS 文件中写了 #box { width: 200px; },但在 JavaScript 中执行 box.style.width 拿到的却是空字符串 ""。
这是因为 element.style 只能读取内联样式(即写在 HTML 标签 style 属性上的内容),无法读取外部样式表计算后的最终表现。若需读取浏览器渲染时生效的最终样式值,必须使用 window.getComputedStyle():
const box = document.getElementById('box');
// 错误做法:拿不到外部 CSS 中定义的属性
console.log(box.style.width); // 输出 ""
// 正确做法:获取计算后的最终样式值
const computed = window.getComputedStyle(box);
console.log(computed.width); // 输出计算后的精确值,如 "200px"
console.log(computed.backgroundColor); // 输出真实 RGB 值,如 "rgb(248, 249, 250)"
五、完整实践示例:手风琴状态卡片
下面是一个将上述知识点综合落地的完整实例。代码演示了从选择器获取、非空判断、监听点击交互,到结合 classList 与 style 共同完成动态效果:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.card-item {
border: 1px solid #d0d7de;
border-radius: 6px;
padding: 16px;
margin-bottom: 12px;
transition: background-color 0.25s ease, border-color 0.25s ease;
}
/* 预定义的激活样式类 */
.card-item.is-selected {
background-color: #F8F9FA;
border-color: #477DAD;
box-shadow: 0 2px 6px rgba(71, 125, 173, 0.15);
}
.badge {
display: inline-block;
padding: 2px 8px;
font-size: 12px;
border-radius: 4px;
color: #ffffff;
background-color: #4F6272;
}
</style>
</head>
<body>
<div class="card-item" id="project-card">
<h4>核心业务模块</h4>
<span class="badge">待处理</span>
</div>
<button id="toggle-status-btn">切换激活状态</button>
<script>
const cardItem = document.getElementById('project-card');
const toggleBtn = document.getElementById('toggle-status-btn');
const badge = cardItem ? cardItem.querySelector('.badge') : null;
if (toggleBtn && cardItem) {
toggleBtn.addEventListener('click', () => {
// 1. 通过 classList 切换整体卡片的选中状态
const isSelected = cardItem.classList.toggle('is-selected');
// 2. 针对内部徽章,根据状态动态修改具体的文字与样式
if (badge) {
if (isSelected) {
badge.style.backgroundColor = '#477DAD';
badge.textContent = '处理中';
} else {
badge.style.backgroundColor = '#4F6272';
badge.textContent = '待处理';
}
}
});
}
</script>
</body>
</html>
在日常开发中,建议优先通过 element.classList 组织绝大部分状态切换,使样式逻辑集中在 CSS 中;当遇到必须依据鼠标坐标、滚动位置等运行时变量时,再辅以 element.style 进行内联微调。遵循这一规范,能够有效保障代码的可维护性与执行性能。
JS监听滚动事件:回到顶部按钮的显示与隐藏逻辑
2026-11-05 16:19:37
JavaScript怎么读写LocalStorage与SessionStorage
2026-11-05 15:40:11
anime.js 与 GSAP 对比:轻量级项目该怎么选择动画库
2026-11-05 11:24:55
flv.js 与 hls.js 在直播场景下的选型对比
2026-11-05 08:18:52
JavaScript能做什么?前端开发中的作用与应用场景解析
2026-11-04 23:17:54








