在Web开发中,使用JavaScript控制页面的视觉表现是很常见的需求。无论是根据用户操作切换主题,还是做动画反馈,本质上都是在运行时改变元素的计算样式。浏览器把CSS解析成CSSOM,脚本能直接碰这块结构,从而在不刷新页面的情况下更新外观。

一、通过element.style直接修改内联样式
最直接的方式是读写DOM元素上的style对象。这个对象对应HTML的style属性,也就是写在标签上的内联样式。因为内联样式优先级高于外部样式表和内部样式块,所以用它改完基本立刻生效,适合做临时、动态的数值调整,比如拖拽改变高度。
需要注意的是,style对象里的属性名采用的是驼峰写法,例如CSS里的background-color在JS里要写成backgroundColor。如果属性名带连字符,必须用方括号语法访问。下面的例子演示了点击按钮让盒子变红并放大:
// 获取目标元素
var box = document.getElementById('box');
// 修改内联样式
box.style.backgroundColor = 'red';
box.style.width = '200px';
box.style.height = '200px';
// 带连字符的属性用方括号
box.style['border-radius'] = '8px';
这种写法的优点是简单直观、即时见效,不需要提前在CSS里定义类。但缺点也很明显:它只改内联,无法利用CSS的层叠与复用;当项目里大量用style改样式,后期很难统一维护,也容易和样式表打架。另外,每次赋值都会触发浏览器的样式重算,连续改多个属性时最好合并到一处或使用requestAnimationFrame减少抖动。
二、通过className与classList切换类名
相比直接写内联,更推荐的做法是先在CSS里定义好状态类,然后用JS切换类名。这样样式逻辑仍由CSS接管,JS只负责表达“现在是什么状态”,结构与表现分离更清晰。className是最早的API,赋值时会被整个替换掉。
例如元素本来有base和active两个类,执行elem.className = 'base hide'就会丢掉active。这在简单场景没问题,但复杂组件里容易误删其他脚本加的类。更安全的方案是classList,它提供add、remove、toggle、contains等方法,可以精准增删单个类而不影响其余。
<style>
.box { width: 100px; height: 100px; background: #ccc; }
.active { background: orange; transform: scale(1.2); }
</style>
<div id="box" class="box">内容</div>
<button id="btn">切换</button>
<script>
var box = document.getElementById('box');
document.getElementById('btn').onclick = function () {
// 只切换active类,不破坏box类
box.classList.toggle('active');
};
</script>
使用类名控制的优势在于:样式集中写在样式表里,便于响应式、伪类配合;多个状态可以组合;不会引起内联优先级混乱。缺点是要提前规划CSS类,动态生成任意颜色这类需求就不太适合纯类名方案。实际项目里,交互状态切换优先用classList,动态数值才用style。
三、修改样式表规则与CSSOM操作
当要全局换肤,或者给页面里某一类元素统一加一条媒体查询规则,挨个改元素就太低效了。此时可以直接操作document.styleSheets,也就是页面引用的所有样式表。通过insertRule或cssRules集合,能在运行时插进新规则或改掉旧规则。
下面示例在文档第一个样式表里插入一条规则,让所有带data-night属性的元素背景变黑。这种方式影响范围大,适合主题切换、动态皮肤等场景,但要注意跨域样式表可能无法读取cssRules,会抛安全错误,所以一般只操作自己域名下的style标签或link。
// 向第一个样式表插入规则
var sheet = document.styleSheets[0];
var rule = '[data-night] { background: #000; color: #fff; }';
sheet.insertRule(rule, sheet.cssRules.length);
// 修改已有规则示例
if (sheet.cssRules[0]) {
sheet.cssRules[0].style.padding = '10px';
}
直接改样式表的好处是一次生效、覆盖全页,不必遍历节点;坏处是调试困难,规则堆积后不好追溯。通常只在框架层或主题系统里用,业务代码尽量少碰。配合前面两种方式,就能覆盖从单元素到全局的大部分改样式需求。
四、性能与注意事项
不管用哪种方式,浏览器都会走“样式重算—布局—绘制”的流程。如果频繁在循环里改style,可能触发多次回流。建议把读写分开:先集中读布局属性,再统一写样式,或者把改动放在requestAnimationFrame里合并。
另外,用style设置的属性可以用getComputedStyle读回计算值,但它返回的是只读对象,不能直接改。若想还原,要么删掉内联属性,要么用removeProperty。理解这些边界,才能写出既灵活又不卡顿的样式控制代码。
var el = document.getElementById('box');
// 读计算样式(只读)
var w = getComputedStyle(el).width;
// 移除内联宽度
el.style.removeProperty('width');
总结来看,JS改CSS并不是只有一种写法。临时数值用style,状态切换用classList,全局规则用样式表操作。按场景选对方法,代码更好维护,体验也更流畅。
JavaScript修改CSS样式CSSOM修改时间:2026-08-05 05:21:27