必须在中写,缺initial-scale=1.0会导致ios safari 9.2等旧版浏览器触发300ms延迟;推荐用touch-action: manipulation优化点击响应,避免fastclick共存,并注意pointer-events: none防穿透。

viewport 必须含 initial-scale=1.0 且写在 里
只写 <meta name="viewport" content="width=device-width"> 不够——iOS Safari 9.2 及更早版本、部分安卓 WebView(如 UC 旧版)仍会等满 300ms。缺了 initial-scale=1.0,浏览器无法确认“这是响应式页面”,双击缩放判定逻辑照常运行。
正确写法是:<meta name="viewport" content="width=device-width, initial-scale=1.0">,且必须静态放在 内。动态插入或写在 里,解析失败,等同于没写。
若需彻底关闭双击缩放(比如管理后台),可加 user-scalable=no 或 maximum-scale=1.0,但注意:这会禁用所有双指缩放,包括用户放大图片的需求。
touch-action: manipulation 是首选 CSS 解法
它明确告诉浏览器:“此处只需处理点击和单指纵向滚动”,既跳过 300ms 判定,又不破坏滚动体验。比 touch-action: none 安全得多——后者会禁用所有手势,包括页面滚动。
使用时注意:
- 只加在有点击意图的元素上,比如
<div class="btn">、React 中包裹 <code>onClick的 wrapper,或自定义组件根节点 - 原生可点击元素(
<button></button>、<a href></a>、<input type="button">)默认已有该行为,除非你写了display: inline-block或显式设了touch-action: auto - IE10/11 需补前缀:
-ms-touch-action: manipulation - 别全局加到
html或body上,否则页面可能无法滚动 - 控制台输入
window.FastClick,返回构造函数说明还在运行 - 全局搜索
new FastClick()或FastClick.attach() - 若已用
touch-action,直接删掉所有初始化代码,无需替换 - 某些 UI 框架(如 Ionic 3)默认内置
FastClick,得查文档关掉对应开关 - 在过渡期间给下层加临时样式:
pointer-events: none,动画结束再移除 - 改用
pointerdown+e.preventDefault()替代 click,但需注意兼容性(iOS Safari 10.3+、Chrome 55+)
别让 FastClick 和 touch-action 共存
两者机制冲突:FastClick 用 JS 模拟 click 并阻止原生 click;touch-action: manipulation 让原生 click 立即触发。共存会导致事件重复、顺序错乱,甚至按钮完全无响应。
排查与清理方法:
穿透问题比延迟更难定位,pointer-events: none 是关键补救
哪怕你用了 touch-action 或已禁用缩放,只要上层弹层在 touchend 后立刻 display: none 或移除,而下层恰好是 <a></a>、<button></button> 或绑了 click 的元素,300ms 后原生 click 仍会落到下层——这个时间差 JS 拦不住。
可靠解法只有两个:
真正容易被忽略的是:这个问题和“有没有延迟”无关,而是“延迟是否被同步拦截”。很多项目调通了 touch-action 就以为万事大吉,结果上线后点透跳转,排查半天才发现是这里漏了。











