正确写法是@media (hover: hover) and (pointer: fine),它要求设备主输入机制既支持悬停又属精细类型(如鼠标、触控笔),精准排除手指触摸等粗粒度场景,避免Surface、S22等设备因误判hover导致:hover样式“卡住”。

为什么@media (hover: hover)在Surface、S22上会误触发
因为这些设备报告同时满足 hover: hover 和 pointer: coarse —— 浏览器照规范执行,把首次触摸当成“悬停开始”,但没有对应的“悬停结束”事件,导致 .menu:hover { display: block; } 点一下就卡住,再点别处也不收。
@media (hover: hover) and (pointer: fine) 才是安全写法
它要求主输入机制既支持悬停,又属于精细类型(如鼠标、触控笔),自动排除手指触摸。这不是“设备类型判断”,而是“当前交互精度判断”:
-
@media (hover: hover) and (pointer: coarse)永远不匹配——规范里两者互斥 -
@media (any-hover: hover)误触率极高,连蓝牙鼠标、手写笔都算,毫无区分度 - iOS Safari 有些版本硬编码
hover: hover为true,哪怕你正用手指点,也骗不过它
transition 必须包进同一媒体查询里
否则移动 Safari 可能单独解析到 transition 属性,导致 Vue/React 组件重渲染时意外动画:
- 别写
transition: all,明确列出要过渡的属性,比如transform、box-shadow - 这个媒体查询只管视觉增强,不参与功能逻辑;
:focus样式仍需单独保留 - 移动端点击必须有
:active替代反馈,iOS Safari 要求可点击性标记(如cursor: pointer或ontouchstart)
真正容易被忽略的点
媒体查询只在页面加载时计算一次,而 pointer 特性会随输入方式动态切换(比如 Surface 插着鼠标又切回触摸)。所以不能靠它“禁用 hover”,而应把它和 hover 解耦:一个负责精细输入动效,一个负责粗粒度交互优化(比如增大热区、调整 focus outline)。混用或写成“或”逻辑(如 @media (hover: hover), (pointer: coarse))反而扩大误触发范围。
立即学习“前端免费学习笔记(深入)”;


















