<p>Tailwind 的 hover:、focus: 等不是 BEM 风格的 modifier,而是 CSS 伪类的编译映射,生成独立选择器规则;需手动启用复合变体(如 focus-hover)和扩展插件支持 first-line、has- 等伪类。</p>

Modifier 在 Tailwind 中不是“状态触发器”,它本身不触发任何行为——hover:、focus:、active: 这些是伪类修饰符(pseudo-class variants),不是 BEM 风格的 modifier。混淆这点会导致样式失效、调试困难。
为什么 hover: 和 focus: 不是 Modifier
Tailwind 的 hover:、focus: 等前缀本质是 CSS 伪类 :hover、:focus 的编译映射,它们生成的是独立的选择器规则,比如 hover:bg-blue-500 → .hover\:bg-blue-500:hover { background-color: #3b82f6; }。这和 BEM 的 --disabled 这类语义化状态 class 完全不同:前者依赖浏览器事件自动切换,后者需你手动增删 class。
-
hover:只对可交互元素生效(<button>、<a>、带tabindex的<div>),纯<div>加了也无效 - 移动端
:hover基本不可靠,:active仅在点击瞬间触发,无法维持 - 写
hover:bg-blue-500 focus:bg-yellow-400 active:bg-red-500并不意味着三者能同时叠加;浏览器只匹配一个伪类链,Tailwind 默认不生成:hover:focus或:focus:active这类组合选择器
如何让 hover 和 focus 同时生效
想实现「输入框聚焦 + 鼠标悬停」双态反馈,必须显式启用复合变体。Tailwind 默认只支持单层伪类前缀,hover:focus:bg-indigo-100 这种写法会被忽略。
- 在
tailwind.config.js的plugins: []中添加插件:
plugins: [
function({ addVariant }) {
addVariant('focus-hover', '&:focus:hover')
}
]
- 之后使用
focus-hover:bg-indigo-100,它会生成.focus-hover\:bg-indigo-100:focus:hover规则 - 顺序有语义:
focus-hover表示“先获得焦点再悬停”,反过来写hover-focus就得定义&:hover:focus(效果等价,但按用户操作流推荐前者) - 不要用
group模拟——group-hover:group-focus:是非法语法,Tailwind 不解析
active: 样式“一闪而过”的真实原因
active: 生效时间极短,不是 Tailwind 的限制,而是浏览器原生行为:
立即学习“前端免费学习笔记(深入)”;
- 桌面端:鼠标按下时触发
:active,但若按下后移出元素再松开,:active会立即结束 - 移动端:触摸开始即触发,但持续时间通常只有几十毫秒,且无法通过 CSS 延长
- 如果需要持久态(比如按钮按下后保持高亮),必须用 JS 切换自定义 class,例如
is-pressed,再配is-pressed:bg-red-600 -
active:和focus:在键盘操作中可能冲突——Tab 进入后按空格触发点击,此时两个状态共存,但 Tailwind 默认没生成:active:focus变体
哪些伪类变体需要手动启用
Tailwind v3.3+ 默认只内置高频伪类(hover、focus、disabled 等)。以下常见需求都得自己注册:
-
first-line:需插件addVariant('first-line', '&::first-line'),且仅支持字体、颜色、行高等有限属性 -
has-:依赖:has(),必须开启corePlugins.has,且注意 Safari 支持度和性能开销 -
empty::Tailwind 官方不支持,empty:hidden会静默失败;得用原生@layer components或兄弟选择器#list:empty + #empty-state -
before:/after::必须显式声明before:content-[""],否则所有before:样式无效;content 值需提前在theme.extend.content中注册
最易被忽略的一点:所有这些变体的生效前提,都是宿主元素本身具备对应语义或 DOM 结构。比如 first: 只认 :first-child,如果父容器第一个子节点是注释或空文本,它就永远不触发——这不是 Tailwind 的 bug,是 CSS 规范本身如此。


















