1、dom.style.width:DOM树的内联样式
直接读取元素内联样式属性,仅反映 HTML 标签中 style 属性定义的值,无法获取外部CSS或内嵌样式表设置的宽度。
返回值特征:
- 仅返回内联样式设置的宽度,未设置则返回空字符串
- 带单位字符串(如"200px"),百分比设置则返回百分比字符串
- 不包含 padding、border 和 margin
关键特性: - 可通过
element.style.width = "300px"直接修改内联样式 - 设置时必须指定单位(如px、em),否则无效
2、getComputedStyle(dom).width:CSSOM树的计算结果
从 CSSOM 树读取计算后样式值,反映所有CSS规则应用后的最终宽度,包括外部样式表、内嵌样式和继承样式。
返回值特征:
- 返回计算后的绝对值(如"200px"),无论CSS中设置的是百分比或em
- 不包含 border 和 margin
关键差异示例:
.box { width: 50%; }
<div class="box" style="width: 200px;"></div>
此时 style.width 返回 "200px",而 getComputedStyle(box).width 返回计算后的像素值(如"512px",取决于父容器宽度)。
注意事项:
- 只读属性,无法通过该方法修改样式
- 每次调用重新计算,可能触发重排
- IE8及以下需用 element.currentStyle 替代
3、dom.clientWidth:布局树的可视内容宽度
从浏览器布局树读取元素内部可视宽度,代表布局引擎计算后的实际占用空间。
返回值特征:
- 数值类型(无单位),四舍五入为整数
- 不包含 border、margin 和 scroll
- 元素隐藏(display:none)则返回 0
计算逻辑: - 标准盒模型(content-box):
clientWidth = contentWidth + paddingLeft + paddingRight - 怪异盒模型(border-box):
clientWidth = contentWidth + paddingLeft + paddingRight + borderLeft + borderRight(此时CSS设置的width已包含这些值)
4、dom.getBoundingClientRect().width:视觉渲染的最终尺寸
返回元素在视口坐标系中的视觉边界矩形宽度,代表元素在屏幕上实际显示的尺寸。
返回值特征:
- 浮点数值(精确到小数位)
- 包含内容区域 + padding + border + scroll
- 受CSS变换(transform)影响,如
scale(1.5 )会使宽度扩大1.5倍 - 相对于视口左上角计算,随页面滚动变化
注意事项: - top、left 值随页面滚动变化,固定位置需加上 pageXOffset、pageYOffset
- 频繁调用可能触发重绘
- 元素有 border-radius 时仍返回矩形边界
性能优化
避免在动画帧中频繁调用 getBoundingClientRect 和 getComputedStyle,建议每帧缓存结果
批量读取尺寸属性,避免读写操作交替触发多次重排
使用 requestAnimationFrame 控制读取时机,减少布局抖动
浏览器兼容
IE8及以下用 element.currentStyle 替代 getComputedStyle
低版本IE中 getBoundingClientRect 不包含 width/height 属性,需通过 right/left 计算
移动端Android 4.4以下 clientWidth 可能包含滚动条宽度
精确测量
小数精度要求高的场景(如canvas绘图)必须使用 getBoundingClientRect
测量隐藏元素尺寸时,临时设置 position: absolute; visibility: hidden 替代 display: none
响应式布局中结合 resizeObserver 监听尺寸变化,而非定时查询
总结
四个API对应浏览器渲染流水线的不同阶段:DOM树(style.width)→ CSSOM树(getComputedStyle)→ 布局树(clientWidth)→ 渲染树(getBoundingClientRect)。实际开发中需根据场景选择。
- 样式修改场景:dom.style.width,直接操作内联样式
- 样式查询场景:getComputedStyle,获取最终计算样式
- 布局计算场景:clientWidth,获取布局宽度用于排版
- 视觉交互场景:getBoundingClientRect,如拖拽、碰撞检测
- 动画场景:getBoundingClientRect().width,获取精确浮点值