你以为 2D 滚动只能靠 Shift 加鼠标滚轮才能斜着滚?今天 CSS 把这件事彻底原生化了
你做了个地图页面,或者画布,或者任何可以往两个方向滚的东西。用户在上面斜着拖了一下——然后浏览器把它切成纯上、纯下、纯左、纯右。中间那个对角线分量,没了。这个行为有名字:scroll axis locking(滚动轴锁定),也叫 railing。多少年了,没人管得了。现在 CSS 给了你一个属性,一行关掉它。
它是怎么工作的
默认情况下,浏览器在滚动手势开始时判断主轴——如果 X 轴偏移量明显大于 Y 轴(或反过来),浏览器就”锁定”这个轴,在本次手势周期内忽略垂直于主轴的输入。
举个例子:用户用触控板拖了一下,X 轴偏移了 3px,Y 轴偏移了 500px。浏览器认为这是在垂直滚动,于是忽略那 3px X 轴偏移,后面的整个手势周期里 X 轴就再也不会动。滑轨效应(railing)就出现了。
这件事在大多数场景下是好的——你在读一篇文章,手指偏了一点,浏览器帮你”修正”成纯垂直滚动,读起来顺畅。但如果你做的是一个地图、一个设计画布、一个楼层平面图,用户的斜向拖拽本身就是输入,锁定单轴就是在和用户作对。
scroll-axis-lock 是 CSS Overflow 5 规范里新增的属性,给你控制这个行为的开关:
.scroller {
scroll-axis-lock: auto; /* 默认,浏览器做主 */
/* 或者 */
scroll-axis-lock: none; /* 关闭锁定,对角线随便滚 */
}
就一行。不需要 JS,不需要监听 wheel 事件算向量,不需要在每次手势开始时判断角度然后手动 blend deltaX/deltaY。这个属性直接告诉浏览器:别替我做这个决定。
实际效果对比
Bramus Van Damme(CSS 领域知名技术作者)做了一个演示,直接用触控板斜向拖动同一块 2D 画布,对比两种值的行为差异:
scroll-axis-lock: auto(默认):斜向输入进去,浏览器选了一个主轴锁定,画布只能沿单个轴移动。对角线分量被吃了。scroll-axis-lock: none:输入向量被完整还原,画布严格跟随手指轨迹,对角线滚动完全成立。
他在 macOS Chrome 153 上测试,发现即使 Chrome 比 Safari 对轴锁定的处理更”宽松”一些,仍然存在锁定行为。这个行为在不同浏览器和操作系统组合下表现不一致——Safari + macOS 非常严格,Chrome + macOS 稍好但也有,Chrome + Android 会锁定,iOS Safari 反而不锁定。这也是为什么长期以来”对角线滚动”在不同平台表现不一,没有人能说清楚规则是什么。
适合哪些场景
这个属性不是给普通文章页用的——普通页面只有一个主轴,根本不存在 2D 滚动。以下才是它的用武之地:
- 地图:用户想斜着平移地图,锁定单轴就直接破坏体验
- 设计画布 / 白板:Figma 这类工具的核心交互,斜向拖动是基本操作
- 楼层平面图 / 座位图:大尺寸图表,用户需要自由探索
- 可缩放的数据可视化图表:zoom + pan 同时发生
- swipe to dismiss:斜向上滑关闭手势,也会被 railing 影响
- 360° 全景图:斜向拖动是标准操作
如果你的产品里有以上任意一种,这个属性值得优先加上。
浏览器支持与渐进增强
现状:
- Chromium(Chrome):✅ 153+ 稳定支持
- Microsoft Edge:✅ 153+ 稳定支持(和 Chromium 同一引擎)
- Firefox:❌ 暂无支持
- Safari:❌ 暂无支持
好消息是退化是安全的。如果你把 scroll-axis-lock: none 写在了一个 Safari/Firefox 不认识的浏览器上,它们只是忽略这行——用户得到的就是该平台默认的滚动行为,什么都不会坏。
所以渐进增强写法不需要 @supports 来兜底,直接写就行:
.map-container {
overflow: auto;
scroll-axis-lock: none; /* Chromium 用户体验对角线滚动,其他用户得到平台默认 */
}
如果你需要针对支持该属性的浏览器做额外样式增强(比如调整交互文案或加载替代交互逻辑),可以用 @supports 来分支:
@supports (scroll-axis-lock: none) {
/* 支持的浏览器里可以展示"支持斜向拖动"提示 */
}
下一步
下一个你做的地图页、画布页、zoom 可视化页面,加上这行就够了。如果你现在用的就是 Figma/Canva 这类工具做设计,它们的 web 版本早就在内部处理过这个问题——而你现在可以把这个能力直接还给 CSS,不再依赖框架内部实现。
三步上生产:
- 找到你的 2D scroller 容器,确认它有
overflow: auto或overflow: scroll - 加一行
scroll-axis-lock: none - 用触控板斜向拖动验收,Chrome 153+ 下对角线分量应该完整保留
评论区
登录后可评论。