ios safari中:active常失效,因需满足绑定触摸事件、cursor:pointer、touch-action:manipulation或为可聚焦元素;应优先加touch-action:manipulation,并用js监听touchstart/touchend切换状态类控制过渡。

transition 本身兼容触屏设备,但 :hover 和 :active 在移动端行为不可靠——必须绕过伪类依赖,用状态类 + 触摸事件显式控制。
为什么 :active 在 iOS Safari 上经常失效
iOS Safari 默认不触发 :active,除非元素满足以下任一条件:已绑定触摸事件、有 cursor: pointer、设置了 touch-action: manipulation,或本身就是可聚焦元素(如 <button></button>)。纯 <div> 或未设交互属性的链接,点下去几乎没反馈。
<ul>
<li>不要只写 <code>.btn:active { transform: scale(0.96); } 就以为完事
touch-action: manipulation;,这是最轻量有效的激活方式ontouchstart="" 这种空属性——它虽能强制激活 :active,但语义差、不利于可访问性用 JS 添加状态类比依赖 :active 更可控
监听 touchstart 添加临时类(如 .touched),再用 touchend 或 touchcancel 移除。这样过渡完全由你掌控,不被浏览器策略卡住。
- 只监听
touchstart,别用click——安卓某些 WebView 会吞掉快速连点 - 过渡时间建议 ≤
0.15s,太长削弱点击即时感 - 类名要和基础 transition 对齐,例如:
.btn { transition: transform 0.15s cubic-bezier(0.25, 0.46, 0.45, 0.94); },然后.btn.touched { transform: scale(0.96); }
避免在滚动中意外触发 transition
Safari 在 scroll 过程中会暂停非合成属性的动画帧,导致 touchstart 后的过渡卡顿甚至丢失。关键不是禁用 transition,而是确保被过渡的属性是 GPU 友好的。
- 只对
transform和opacity做过渡,别碰top、left、width - 如果按钮在吸顶导航里,用
position: sticky+transform位移,而不是靠 JS 改top - 别在
scroll事件里频繁增删 class;改用IntersectionObserver或节流后仅在临界点操作
真正麻烦的不是 transition 写法,而是不同机型对触摸事件的响应节奏差异——有的点一下就触发,有的要等 300ms 才算“确认点击”。所以过渡时长不能一刀切,得结合 touch-action 和状态类双保险。











