应使用 CSS 媒体查询 (hover: hover) and (pointer: fine) 启用悬停效果,(hover: none) and (pointer: coarse) 识别纯触控场景,并配合 :active、focus-within 及 JS 动态监听 pointerdown 与 matchMedia change 事件实现精准输入适配。

直接用屏幕宽度或 UA 字符串判断是否支持悬停,已经不可靠。真正该做的是让浏览器自己报告它的输入能力——用 CSS 媒体查询检测 hover 和 pointer 的实际状态。
用 (hover: hover) and (pointer: fine) 启用鼠标悬停效果
这个组合表示设备主输入方式既支持可靠悬停,又具备精细指针(如鼠标、触控笔)。只有满足这两个条件,才启用 hover 动画和交互增强:
- 所有 hover 相关样式(包括 transition)必须统一包进该媒体查询内,避免基础样式中单独定义 transition 导致触屏误触发
- 不要在外部写 .card:hover,否则 iOS Safari 点一次闪一下阴影,再点就失效,甚至导致下拉菜单意外关闭
- Surface Pro、iPad Pro 这类设备横屏时宽度超 1024px,但仅靠 max-width 判断会漏掉它们的悬停能力
用 (hover: none) and (pointer: coarse) 识别纯触控场景
这是目前最稳定、兼容性最好的触控判定方式,能准确捕获“当前只能靠手指操作”的状态:
- 它比单一 (hover: none) 更精准,因为有些安卓设备误报 hover: hover,但 pointer: coarse 几乎不会错判
- 适合默认展开导航下拉项、常驻 tooltip、增大点击热区等触控友好调整
- iOS 13.4+ 和 ChromeOS 设备即使接了鼠标,只要当前是手指操作,该组合仍可正确匹配
补足触控反馈,不能只删 hover
禁用 hover 不等于完成适配。用户点下去没反应,第一感觉就是“没点中”:
立即学习“前端免费学习笔记(深入)”;
- :active 必须保留,但 iOS Safari 默认不响应,需给元素加 cursor: pointer 或监听 pointerdown 才激活
- 关键按钮建议加轻量 tap 动画:transform: scale(0.95),持续时间 ≤ 150ms,避免拖慢响应
- 对重要操作区域(如菜单项、卡片)补充 focus-within 或 JS 模拟的视觉反馈,确保键盘与触控用户都可感知
用 JavaScript 动态响应输入方式切换
CSS 媒体查询只在页面加载时计算一次,而用户可能中途插拔鼠标或从桌面切到平板模式:
- 监听 pointerdown 事件,检查 event.pointerType === 'touch',临时标记当前为触控模式
- 用 window.matchMedia('(hover: none)').matches 初始化状态,并监听 change 事件更新 body class
- 推荐给 body 添加 has-hover 或 no-hover 类,用 CSS 分支控制样式,而非直接操作 DOM
- 避免监听 touchstart——现代 iOS 已禁用该 API,且 Windows 平板可能同时触发 touchstart 和 mousedown,造成样式抖动



















