核心是用原生的oninput事件实时控制clip-path: inset(0 calc(100% - x%) 0 0)裁剪图片,兼容ie10+,需处理safari触摸、图片加载占位及宽高比适配。

用 input[type="range"] 控制图片对比滑块位置
左右拖动的核心不是靠 JS 手动监听鼠标,而是用原生 <input type="range"> 绑定宽度变化。它天然支持拖拽、键盘方向键、触摸滑动,兼容性好(IE10+),且无需额外事件防抖或边界判断。
关键点:滑块的 value 值映射为对比分界线的 left 百分比(0–100),同时控制左侧图片的 clip-path 或容器宽度。
-
<input type="range" min="0" max="100" value="50">是基础控件,value初始设为 50 表示居中 - 不要用
onchange——它只在松手后触发;改用oninput实现实时响应 - 把
input放在图片容器外层,避免遮挡或干扰点击区域
用 clip-path 实现左侧图片裁剪(现代方案)
比起用两个重叠 <img> + 绝对定位 + 宽度缩放,clip-path 更简洁、无重绘抖动、不破坏语义结构。只需一个 <img>,用 inset(0 calc(100% - X%) 0 0) 动态裁剪右侧部分。
注意:Chrome/Firefox/Edge 支持良好,Safari 15.4+ 才完全支持 inset() 的百分比参数;若需兼容旧 Safari,得 fallback 到 width 控制。
- HTML 中只放一张完整图片:
<img src="before-after.jpg" alt="对比图"> - CSS 设置:
clip-path: inset(0 calc(100% - 50%) 0 0);—— 这里50%对应初始滑块位置 - JS 更新时,直接拼接字符串:
img.style.clipPath = `inset(0 calc(100% - ${value}%) 0 0)`;
处理移动端触摸拖拽失效问题
默认情况下,<input type="range"> 在 iOS Safari 上可能响应迟钝或无法拖动,尤其嵌套在 <div> 里时。根本原因是 Safari 对 touch-action 的默认限制。<ul>
<li>给 <code>input 加 CSS:touch-action: auto;(不是 pan-x,后者会禁用垂直滚动)
overflow: hidden 或 pointer-events: none 意外拦截事件input { -webkit-appearance: none; },再自定义滑块样式(否则 Safari 会降级为不可拖动的按钮)图片加载完成前避免布局跳变和裁剪错位
图片未加载完时,<img> 高度为 0,clip-path 计算会出错,导致拖动后分界线偏移或消失。
- 给
<img>设固定宽高或aspect-ratio:aspect-ratio: 16/9;(推荐) - 监听
img.onload后再启用滑块:input.disabled = false;,初始设disabled - 或者用
img { display: block; min-height: 200px; background: #eee; }占位,避免闪动
真正麻烦的是图片宽高比不一致时的适配——要么统一裁剪(用 object-fit: cover),要么让容器按图片原始比例撑开(需要 JS 读取 naturalWidth/naturalHeight)。这点容易被忽略,但一上线就暴露。











