地图拖拽总是被浏览器掰直?Chrome 153 把对角线滚动这件事彻底解了
做 2D 地图、白板、大图浏览时,浏览器总把手势“钉”在主轴,对角线拖拽变成两段式。这件事终于有一个原生 CSS 开关了。
问题:不是手势不准,是浏览器帮你做了决定
当你做一个可双轴滚动的容器时,浏览器默认会做一件事:scroll axis locking,也叫 railing。简单说,如果用户手势在某轴上占主导,浏览器就会忽略另一轴的微小 delta,把滚动锁死到主轴上。
这通常是对的。看长文章时,轻微横向漂移会被压掉,体验更稳。但它在地图、大画布、架构图、可缩放图片这些场景里就是灾难。用户 45 度划过去,浏览器却只响应主轴,对角线变成了“先横后竖”的两段。
你之前能做的办法都不优雅:自己 touch/mouse 事件算 dx/dy、改 transform、或者干脆放弃原生滚动全 JS 模拟。这些都是用主线程换“原生滚动”不给你做的事。
方案:scroll-axis-lock: none
CSS Overflow 5 引入了 scroll-axis-lock,语义非常直接。
.map {
overflow: auto;
scroll-axis-lock: none;
}
none 的意思是:这个容器不要做轴锁定,让用户手势的 X/Y 分量都直接进入滚动。
它和 touch-action 不是一回事。touch-action 管的是“浏览器要不要拦截手势”,而 scroll-axis-lock 管的是“浏览器已经开始滚之后,要不要锁轴”。前者管开头,后者管过程。这也是为什么它能覆盖 trackpad、mouse wheel 和 touch:不管输入源是什么,只要进入滚动阶段,这个声明都生效。
现状:Chrome 153 已支持,其他引擎还没跟上
根据 Bramus 的实测和 Chrome Platform Status:
- Chromium 153:已支持
- Firefox:无支持信号
- Safari:无支持信号
所以现在的正确用法是渐进增强,不是条件分支。
@supports (scroll-axis-lock: none) {
.map {
scroll-axis-lock: none;
}
}
不支持的浏览器直接忽略,完全不会回退;支持的浏览器则在原生滚动层面解锁双轴。这比你自己在 JS 里算手势要稳得多。
底层逻辑:为什么浏览器原来要锁轴
滚动轴锁定本质是浏览器在替用户做“意图压缩”。在手势追踪里,用户几乎不可能做到绝对直线的 45 度。鼠标和触控板的原始输入都会带有轻微抖动。浏览器为了避免页面斜着飘,就选一个主轴,忽略另一轴的小 delta。
这个设计在内容流里是对的,但在 2D 界面里是反直觉的。用户想要的就是同时移动两个轴,浏览器却把另一轴没收了。
scroll-axis-lock 所做的,不是推翻这个策略,而是把它从“全局默认”变成“按容器可配置”。
怎么判断你该不该用
如果你的页面只有单轴列表、普通文章流、横向轮播加纵向页面,那这件事和你没关系,auto 是对的。
如果你的容器是以下任一场景,才需要考虑:地图、大画布/白板、流程图/架构图/seating chart、可缩放的 2D 预览、全景图/360 图。这些场景的共同点是:用户需要从任意角度开始拖拽,而且初始方向本身就是内容的一部分。
下一步
如果你手上有这类 2D 滚动容器,可以先用 @supports 加上 scroll-axis-lock: none,不破坏现有行为,但在 Chrome 153+ 上直接获得原生对角线滚动。
接下来要盯的是 Firefox 和 WebKit 的信号。这个属性在规范里的定位很稳,问题只是实现时间。如果你之前为了“对角线滚动”自己写过 gesture blending,现在可以开始考虑收缩掉了。
评论区
登录后可评论。