hover: 和 active: 是 Tailwind 的状态修饰符前缀,需与样式类组合使用,依赖 CSS :hover/:active 伪类,仅对可交互元素生效;常见失效原因包括 pointer-events 干预、transform 错位及无障碍媒体查询限制。
Tailwind 的 hover: 和 active: 不是独立类,而是状态修饰符前缀,必须和具体样式类组合使用,比如 hover:bg-blue-500 或 active:scale-95。它们底层依赖 CSS 的 :hover 和 :active 伪类,所以只对支持这些伪类的元素(如 <a>、<button>、带 tabindex 的 <div>)有效。
常见错误现象:hover:text-red-400 加在 <span> 上没反应——因为 <span> 默认不可交互,浏览器不触发 :hover(尤其在移动端 Safari 中更敏感)。
<button> 或给 <div> 加 tabindex="0"
active: 在触摸设备上行为不稳定,部分安卓浏览器会跳过 :active 或延迟触发,别依赖它做关键视觉反馈hover:underline active:opacity-80 focus:ring-2,但注意层叠顺序不影响优先级,CSS 规则仍按写入顺序覆盖不是 Tailwind 编译问题,而是 CSS 层叠或平台限制导致。最常被忽略的是父级 pointer-events 干预、CSS 变换破坏触发区域、或媒体查询屏蔽了响应式悬停。
pointer-events: none(比如某些遮罩层),子元素的 hover: 完全失效——改用 pointer-events: auto 覆盖transform(如 hover:scale-105)但父级没触发硬件加速,某些 Chrome 版本下悬停区域错位;加 will-change: transform 或 translateZ(0) 类临时修复@media (prefers-reduced-motion: reduce) 下,Tailwind 默认禁用所有 hover: 动画(包括 hover:scale、hover:duration-300),需手动重写或用 motion-safe: 显式启用active: 在 iOS Safari 和多数安卓 WebView 中,仅在“按下且未松开”瞬间触发,松开后立即回退,且无法维持——这意味着你不能靠它模拟“按住不放”的长按态,也不适合做开关切换的视觉锚点。
立即学习“前端免费学习笔记(深入)”;
更可靠的替代方式:
touchstart/mousedown 添加 is-active 类,再配 active:opacity-75 作为降级focus-visible: + data-[state=active](配合 Headless UI 或 Radix)实现跨平台一致的激活反馈active: 做功能判断,比如不要写 active:bg-green-600 表示“已选中”,而该用 data-[selected]:bg-green-600 配合 JS 状态更新如果你在 tailwind.config.js 里扩展了 variants(旧版)或 plugins 添加了类似 disabled:、loading: 的修饰符,务必确认它们被 PurgeCSS 扫描到——否则生产环境可能丢失样式。
content 路径配置,或在模板中实际写出对应类(如 loading:opacity-50),否则会被清除class="hover:{{ variant }}-500"(Vue/JSX)不会被 PurgeCSS 识别,应改用 </li><li>调试时运行 <code>npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify --watch并检查输出文件是否含预期规则,比肉眼检查更快
真正难的不是写对 hover:,而是预判它在哪种设备、哪种交互路径下会静默失败。多在真机上点按、长按、快速滑动测试,比看文档更管用。