在做移动端交互时,有一种场景非常常见:
外层容器负责左右拖动,内层容器负责上下滚动。
例如:

看起来这个需求并不复杂。但是我在实际开发时遇到了一个问题:
内层元素内容过多,加上
overflow: auto之后,外层的横向拖动突然变得不正常。
例如:

经过排查发现将 overflow: auto; 改成 overflow: hidden; 外层横向拖动又恢复了。
经过吉米尼老师的提醒,发现一个CSS属性:touch-action
css
touch-action: pan-y;
表示:
告诉浏览器,这个区域的纵向平移可以由浏览器处理。
而其他没有交给浏览器处理的手势,可以由 JavaScript 自己实现。
MDN 对 touch-action 的描述也是这个思路:浏览器会根据 touch-action 确定哪些触摸手势由浏览器处理,应用程序则可以处理剩余的手势。
那现在还有一个问题:
浏览器到底应该如何处理用户的触摸手势?
这时候就需要:
css
touch-action: pan-y;
完整写法:
css
.scroll {
height: 100%;
overflow-x: hidden;
overflow-y: auto;
touch-action: pan-y;
}
这实际上是在明确表达:
这个区域允许浏览器处理纵向平移。
而横向拖动则由 Pointer Events 自己处理。
总结:
overflow负责定义"内容在哪个方向可以滚动",touch-action负责定义"浏览器可以处理哪些触摸手势",JavaScript 则负责实现剩下的自定义手势。把三者的职责分清楚,移动端的手势冲突自然就容易解决了。