原生 scrollbar 在迷你编辑器中不适用,因其尺寸大、样式不可控、易遮挡内容且 hover 占位;VSCode 迷你滚动条需淡入、无轨道、6px 宽、紧贴右、不抢焦点,原生伪类无法干净实现;故采用 overflow: hidden + 自定义 div 滚动条,通过监听 wheel/touch、手动更新 scrollTop、动态计算滑块位置与高度、加 transition 和 pointer-events 精确控制交互,并在移动端 touchmove 中显式 preventDefault() 且设置 passive: false。

为什么原生 scrollbar 在迷你编辑器里不适用
原生滚动条默认尺寸大、样式不可控,且在小高度容器(比如 200px 高的代码预览区)里会遮挡内容、触发不必要的 hover 占位。VSCode 的迷你滚动条只在滚动时淡入、无拖拽轨道、宽度固定为 6px、紧贴右侧、不抢焦点——这些都不是 ::-webkit-scrollbar 能干净实现的。
用 overflow: hidden + 自定义 div 滚动条最可控
放弃劫持原生滚动行为,改用 overflow: hidden 包裹内容区,再用绝对定位的 div 模拟滚动条轨道和滑块。关键点:
- 监听
mousewheel或touchmove,手动更新内容区scrollTop - 滑块高度 =
containerHeight * containerHeight / scrollHeight,实时计算 - 滑块位置 =
(scrollTop / (scrollHeight - containerHeight)) * trackHeight - 加
transition: top 0.1s ease-out让滑动更顺滑 - 鼠标按下滑块时,绑定
mousemove并阻止默认行为,避免文字选中
pointer-events: none 是隐藏交互干扰的关键
滚动条轨道本身不该响应点击或 hover,否则会影响背后的代码行点击。常见错误是给整个滚动条容器设 pointer-events: none,结果导致滑块也无法拖拽。正确做法:
- 轨道
div.track设pointer-events: none - 滑块
div.thumb单独设pointer-events: auto - 同时给滑块加
user-select: none,防止拖拽时误选中文本
漏掉任意一条,都可能表现为“点不动”“一拖就跳”或“松手后还在滚动”。
立即学习“前端免费学习笔记(深入)”;
移动端适配要单独处理 touchstart/touchmove
桌面端靠 mousedown/mousemove 可以,但 iOS Safari 和 Chrome Android 对 mousewheel 支持不稳定,且 touch 操作会触发默认滚动,必须显式 preventDefault()。实操要点:
- 在容器上监听
touchstart,记录初始scrollTop和触摸 Y 偏移 -
touchmove中计算位移差,更新scrollTop并同步滑块位置 - 务必在
touchmove里调用e.preventDefault(),否则原生滚动会覆盖你的逻辑 - 加个
{ passive: false }到事件监听选项,不然 Safari 会静默忽略preventDefault
没加 passive: false 是移动端滚动条失效最隐蔽的原因——控制台不报错,但就是不响应触摸。



















