Chrome Mobile中CSS :active状态的JS事件监听及延迟问题
解决Chrome Mobile中:active状态与触摸/点击事件不同步的问题
主问题:如何为:active状态变化添加JavaScript监听器?
没有直接监听CSS :active伪类状态变化的JavaScript API。你可以通过绑定用户交互事件来精准控制高亮逻辑——用自定义CSS类代替:active,在触摸/按下事件触发时添加类,在松开/取消事件触发时移除类,完全绕过原生:active的延迟问题。
额外问题解答
1. 能否消除touchstart与:active之间的约130ms延迟?
可以,有几种有效方案:
- 给页面元素添加
touch-action: manipulationCSS属性,告知浏览器无需处理双击缩放,直接响应触摸事件; - 确保已正确设置viewport元标签(你代码中已经添加了
<meta name="viewport" content="width=device-width,initial-scale=1"/>,这是基础前提); - 放弃原生
:active,用前面说的自定义类+事件绑定的方式实现高亮,完全规避伪类的延迟。
2. 为何Chrome 108中仍存在该问题?
虽然2015年后主流浏览器逐步移除了300ms双击缩放延迟,但原生:active在触摸场景下的触发逻辑和触摸事件不同步是另一个问题:浏览器为了区分用户是点击还是滑动操作,会调整:active的触发时机,导致视觉反馈和触摸动作出现延迟。此外,如果页面未明确禁用双击缩放,浏览器可能保留部分延迟逻辑。
3. 触摸延迟不是2015年就解决了吗?
是的,传统的300ms双击缩放延迟在正确配置viewport的情况下已经被移除,但你遇到的:active延迟属于浏览器处理伪类状态与触摸事件序列的逻辑差异,并非传统的缩放延迟,所以会存在不同步的情况。
修改后的代码示例
用自定义类模拟高亮,精准同步触摸/点击动作:
<html> <head> <meta name="viewport" content="width=device-width,initial-scale=1"/> <style> html, body, pre { position:absolute; top:0; left:0; right:0; bottom:0; margin: 0; user-select: none; touch-action: manipulation; /* 禁用双击缩放,加速事件响应 */ } pre {margin: 10px; overflow-y:auto} /* 自定义高亮类,替代:active */ pre.highlight { background-color:#fee; } </style> </head> <body> <pre id="ELEM"></pre> <script> const ELEM = document.getElementById("ELEM") ELEM.appendChild(document.createTextNode("")); function Print(s) { let t = (new Date() / 1000 % 60).toFixed(2).padStart(5,0); ELEM.firstChild.nodeValue += `${t}: ${s}\n`; ELEM.scrollTop = ELEM.scrollHeight; } Print("Hello, world!"); // 控制高亮的函数 function addHighlight() { ELEM.classList.add('highlight'); Print('触发高亮'); } function removeHighlight() { ELEM.classList.remove('highlight'); Print('移除高亮'); } // 绑定触摸事件 ELEM.addEventListener('touchstart', addHighlight, {passive: true}); ELEM.addEventListener('touchend', removeHighlight); ELEM.addEventListener('touchcancel', removeHighlight); // 绑定鼠标事件 ELEM.addEventListener('mousedown', addHighlight); ELEM.addEventListener('mouseup', removeHighlight); ELEM.addEventListener('mouseleave', removeHighlight); // 保留原有的事件监听用于调试 const EVENTS = ["mouseup", "mousedown", "touchstart", "touchend", "click", "touchcancel", "mouseenter", "mouseout", "focusin"]; for (let e of EVENTS) { document.body.addEventListener(e, () => {Print(e)}); } </script> </body> </html>
内容的提问来源于stack exchange,提问作者personal_cloud
相关产品推荐
相关产品推荐

