真正可靠的触控能力判断方案是组合使用 hover 和 pointer 媒体特性:@media (hover: none) 表示主输入机制无法稳定悬停,应禁用 :hover 样式;@media (hover: hover) 才启用精细交互;@media (pointer: coarse) 仅提示精度,需与 hover 组合使用;避免依赖 useragent、ontouchstart 等不可靠检测。

不能用 @media (max-width: 768px) 或 navigator.userAgent.includes('Mobile') 判断触控能力——它们匹配的是尺寸或字符串,不是输入行为本身。真正可靠的方案是组合使用 hover 和 pointer 媒体特性。
@media (hover: none) 是判断“无悬停能力”的关键
这个查询不等于“是手机”,而是说设备主输入机制无法稳定维持悬停状态。绝大多数 iOS/Android 设备默认返回 hover: none,包括 iPad(未接鼠标时)、折叠屏展开态、甚至某些带触控的 Linux 笔记本。
-
@media (hover: none)匹配后,应默认禁用:hover样式(如背景色变化、下拉菜单自动展开),避免误触和视觉粘滞 -
@media (hover: hover)才适合启用精细交互:按钮:hover高亮、tooltip 浮层、二级菜单延迟展开 - Safari 15.4+ 才完整支持;旧版 iOS Safari 会忽略整个媒体块,属于安全降级,无需额外兜底
@media (pointer: coarse) 不是“触控开关”,而是精度提示
pointer: coarse 表示至少有一个输入设备是粗粒度的(比如手指),但它和 hover: none 不互斥——Surface Pro 接蓝牙鼠标时可能同时满足 pointer: coarse 和 hover: hover。
- 适合调整点击热区:
min-height: 44px、padding: 12px,防止手指误点 - 不适合单独用作布局切换依据,桌面触控屏、遥控器、游戏手柄也会触发
coarse - 更稳妥的写法是组合:
@media (hover: none) and (pointer: coarse),覆盖典型触屏场景
别用 'ontouchstart' in window 驱动 CSS
这个 JS 检测只说明浏览器“注册了 touchstart 事件”,不代表设备有物理触摸能力。Chrome 桌面版、Edge 模拟器、部分 Linux 浏览器都返回 true,把它塞进 class 再写 CSS,会导致样式错乱且不可维护。
- 它和
@media (hover: none)不等价:一台 iPad 连妙控板后,'ontouchstart' in window仍为true,但@media (hover: hover)已生效 - 纯 CSS 分支必须用媒体查询,JS 只应在需要动态状态管理时补充(如点击展开/收起菜单)
- 若真要用 JS,优先选
window.matchMedia("(hover: none) and (pointer: coarse)").matches
最易被忽略的一点:这些媒体特性是动态响应的。iPad 插上鼠标后,@media (hover: hover) 会立即生效,:hover 样式随之启用——你写的 CSS 必须能承受这种实时切换,而不是假设“移动端永远固定”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











