@media (hover: hover) and (pointer: fine) 是唯一安全写法,单独用 hover 或 pointer 判断均不可靠;基础样式须写在媒体查询外,移动端需用 :active 替代 hover 且加 cursor: pointer 启用。

用 @media (pointer: fine) 包裹 hover 样式才安全
只靠 @media (hover: hover) 不够,它在部分 Android WebView 中会误报为 hover: hover,但实际悬停不可持续。必须叠加 pointer: fine 过滤——这个组合才是现代浏览器识别“真鼠标/触控板设备”的事实标准。
常见错误是单独写 @media (pointer: coarse) 然后清空 hover 样式,这会让 Surface Pro 插着鼠标时也失去悬停反馈。
-
@media (hover: hover) and (pointer: fine)是唯一推荐写法,缺一不可 - 不要写
@media (hover: none)—— Safari 和旧版 Chrome 完全不支持该值,规则会被忽略 - 基础样式(如
transition、默认transform)必须写在媒体查询外,否则移动端动画会突兀跳变
:hover 在触摸设备上失效的根本原因不是尺寸
很多开发者习惯用 @media (max-width: 768px) 禁用 hover,结果 iPad 横屏时 hover 失效,Surface Pro 缩小窗口却仍有 hover 需求。这不是 bug,是输入机制错配:iPhone 即使窗口宽 1200px,手指也无法悬停;而 Surface 连着鼠标时,哪怕窗口只有 400px,hover 依然有效。
- 悬停能力取决于输入设备类型,不是视口宽度
- 桌面端缩放浏览器到小尺寸,
max-width会误判为移动端,关闭本该存在的交互增强 - 二合一设备是最大雷区,仅靠断点无法覆盖真实使用场景
移动端必须提供 :active 替代反馈,且需主动启用
iOS Safari 默认禁用 :active 伪类,除非元素有 cursor: pointer 或监听了 touchstart。直接写 .btn:active { opacity: 0.8; } 在 iPhone 上基本没反应。
- 给所有可点击元素加
cursor: pointer,这是最轻量的启用方式 - 对关键按钮,用
:active { transform: scale(0.98); },时间控制在 150ms 内 - 避免用
click事件模拟——300ms 延迟 + 滚动冲突,体验明显滞后
Scale 放大后文字模糊?加 translateZ(0) 强制 GPU 加速
transform: scale(1.03) 在 Safari/Chrome 中会触发 subpixel 渲染,导致字体边缘轻微发虚。这不是代码错误,但用户能感知。
- 写成
transform: scale(1.03) translateZ(0)可缓解模糊,且兼容性好 - 慎用
will-change: transform—— 只在高频交互组件(如悬浮球菜单)上加,滥用反而增加内存开销 - 避免
scale(1.15)这类非整数倍缩放,优先选scale(1.05)或scale(1.1),像素对齐更稳
transform 创建的新层叠上下文:它可能让遮罩层被压在底下,或让 fixed 导航栏意外偏移。这类问题没法靠加一行 CSS 解决,得先 inspect 元素看 computed 层叠顺序。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











