用 transform 替代 width/left 可避免拖动卡顿:左侧图层 scalex(ratio),右侧图层 translatex(calc(-100% + 100% * ratio)),父容器 overflow: hidden 并缓存尺寸、节流更新、统一单位。

直接用 width 动态改两个 position: absolute 图层的宽度,拖动时会卡顿、错位、甚至白屏——这不是 JS 写得不对,而是 CSS 重排(reflow)被高频触发了。
为什么 width 百分比在拖动中会失准
很多人把滑块值映射成 left: 65% 或 width: 65%,看似合理,但问题出在两点:
- 浏览器对
width的百分比计算依赖父容器当前 layout 尺寸;而 resize 或图片加载完成瞬间,父宽可能未稳定,getBoundingClientRect().width读取不准 -
width变更会强制触发 layout,拖动时每帧都重排,低端设备明显掉帧 - 移动端 touchmove 触发频率高,没节流就直接爆 layout
用 transform + offset 替代 width 控制可见区域
真正轻量、稳定、兼容的方案是:左侧图层缩放,右侧图层平移,共用一个 ratio(0–1)值,全部避开 width 和 left 的 layout 触发点。
- 左侧图层(基准图):
transform: scaleX(ratio),transform-origin: left - 右侧图层(覆盖图):
transform: translateX(calc(-100% + (100% * ratio))),或更稳妥的left: calc(-100% + (100% * ratio))(前提是父容器position: relative) - 父容器必须设
overflow: hidden,否则右侧图层平移后会溢出 - 不要用
clip-path: inset(0 Xpx 0 0)动态算像素值——Safari 旧版不支持动态inset(),且单位混用易出错
JS 更新时必须绕开 layout thrashing
每次鼠标/手指移动都读 offsetWidth 或写 style.width,等于主动邀请卡顿。关键不是“怎么算”,而是“怎么不触发重排”。
- 初始化时缓存容器
container.offsetWidth,后续只读这个值,不反复调getBoundingClientRect() - 更新样式前加
requestAnimationFrame节流,避免连续 layout - 移动端
touchmove必须加e.preventDefault(),否则 iOS Safari 会截断事件流,导致滑块不动 - 别用
will-change: width,它反而干扰渲染节奏;换成will-change: transform更安全
最常被忽略的一点:所有 transform 和 left 值必须统一用百分比或 calc(),不能一半写 50%、一半写 200px——resize 后像素值不会自适应,分界线立刻偏移。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











