@media (hover: hover) and (pointer: fine) 才能可靠识别鼠标,@media (hover: none) and (pointer: coarse) 才能贴近真实触控场景——单用 hover 或 pointer 都会误判。

@media (hover: hover) and (pointer: fine) 才能可靠识别鼠标,@media (hover: none) and (pointer: coarse) 才能贴近真实触控场景——单用 hover 或 pointer 都会误判。
为什么 @media (hover: hover) 单独用在 iPad/Surface 上永远为 true
这不是 bug,是规范行为:只要设备“有能力悬停”(比如插过蓝牙鼠标、连过触控板),浏览器就必须上报 hover: hover。iPadOS 13.4+、ChromeOS、macOS Safari 全部照做,哪怕你正用手指点屏幕,它也返回 true。
-
@media (hover)缺值 → 整条规则被忽略,CSS 不生效 -
@media (any-hover: hover)更危险:Surface 插着触控笔就命中,和当前操作无关 -
@media (max-width: 768px)完全不相关:Windows 触控笔记本也会被当“手机”,导致 hover 卡住 - 真正要问的不是“设备能不能悬停”,而是“这次点击是不是由鼠标/触控笔发起”
@media (hover: hover) and (pointer: fine) 是鼠标安全守门员
这条组合规则强制要求:主输入既支持悬停,又属于精细类型(pointer: fine),自动排除手指、触控板、遥控器等所有粗粒度输入。
- 必须写全值:
(hover: hover)和(pointer: fine)缺一不可 - transition 动画也要包进去,否则 iOS Safari 可能解析到但不触发
:hover - 它不干扰
:focus或键盘导航,无障碍依然可用 - 旧版微信 X5 内核、UC 浏览器基本忽略,属渐进增强,不能当功能开关
@media (hover: none) and (pointer: coarse) 才是触控优化起点
这是目前最贴近“此刻只能触控”的 CSS 判断方式,Safari 14.1+、Chrome 51+、Firefox 62+ 全支持,渲染前就生效。
立即学习“前端免费学习笔记(深入)”;
- 别用
ontouchstart检测:桌面 Chrome DevTools、Linux 浏览器都可能返回 true - 别混用
any-pointer: coarse:Surface 配了触控笔就命中,但用户正在用鼠标 - 典型用途:增大按钮
min-height: 48px、默认展开下拉菜单、禁用纯:hover触发的 tooltip - 注意动态性:iPad 连键盘鼠标后,
pointer可能从coarse切成fine,样式需响应变化
纯 CSS 无法响应输入方式切换,JS 必须补位
CSS 媒体查询只在初始渲染或窗口 resize 时重算,不会监听“用户从鼠标抬手、换手指点”的瞬间。这时候得靠 JS 监听 pointerdown 和 matchMedia 变化。
- 监听
window.matchMedia('(hover: none)').matches,比轮询高效 - 首次
pointerdown且event.pointerType === 'touch',可临时标记“当前触控模式” - 别依赖
touchstart:iOS 已禁用该属性检测,且有 300ms 延迟 - 避免手动切 class:快速连点易导致 class 未清除就重复添加,引发触摸穿透
浏览器根本不暴露“是否有物理触摸屏”,只上报当前主输入能力状态——这个状态是动态的、可切换的。写死判断等于放弃混合设备用户。


















