禁双击放大需 viewport 与 JS 双重拦截:viewport 设 width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0;JS 在 document.documentElement 上监听 touchstart,event.touches.length>1 时 preventDefault()(passive: false)。

viewport 中 maximum-scale=1.0 比 user-scalable=no 更可靠
现代 iOS(10.3+)和多数 Android 浏览器已无视 user-scalable=no,不是你写错了,是浏览器主动拒绝执行。它被视作可访问性障碍,尤其在长按输入框触发放大镜时必然绕过。真正被广泛尊重的组合是:width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0。
必须同时写全这四项:漏掉 initial-scale=1.0,某些安卓机首次加载会意外缩放;漏掉 minimum-scale=1.0,横屏时可能因 viewport 宽度变大而裁切内容;maximum-scale=1.0 是双指缩放的实际闸门,比 user-scalable=no 更底层、更稳定。
overscroll-behavior: none 只对 iOS 16.4+ 有效
overscroll-behavior: none 能禁掉滚动到顶/底时的橡皮筋回弹,但它只在 Safari 16.4+(即 iOS 16.4+)中生效。老 iOS(如 15.x 或更早)完全不识别该属性,加了也白加。
它还必须作用于实际滚动容器上,比如 #app 或 .modal-content,写在 html 或 body 上无效。常见错误包括:
立即学习“前端免费学习笔记(深入)”;
- 给
body设overscroll-behavior: none→ 无效果 - 容器没设
overflow-y: auto或scroll→ 不构成“可滚动上下文”,属性被忽略 - 父级用了
transform或contain: paint→ 创建新层叠上下文,中断控制链
双击放大必须靠 JS + viewport 双重拦截
仅靠 viewport 无法彻底禁双击放大——iOS 在页面内容高度超出视口(document.documentElement.scrollHeight > window.innerHeight)时,会强制启用双击放大以查看溢出区域。
实操建议用轻量 JS 拦截,但要注意细节:
- 监听
document.documentElement上的touchstart,判断event.touches.length > 1并调用event.preventDefault() - 必须传
{ passive: false },否则 Chrome/Safari/Edge 会静默忽略preventDefault() - 别用
ontouchend全局拦截,那会直接废掉所有click事件 - 双击本质是两次
touchend间隔 ≤ 300ms,需缓存时间戳并拦截第二次
overflow-x: hidden 必须同时作用于 html 和 body
禁止左右滑动不能只写 body { overflow-x: hidden }。iOS Safari 的滚动根节点是 html,只设 body 会被透传,左右滑动照常发生。
正确写法是:
html, body {
overflow-x: hidden;
overflow-y: auto;
}
注意两点:
- 加
overflow-y: auto明确保留垂直滚动能力,避免误伤 - 如果页面有
position: fixed弹层,需单独给它加overflow-x: visible,否则会被父级裁剪
即使这样做了,iOS 仍可能在边界留下视觉上的弹性拉伸反馈(灰白蒙层),这是系统级行为,CSS 无法消除——这不是 bug,是平台限制。


















