:hover不生效主因是元素默认不可交互,需加cursor: pointer;:active仅在按住时触发,需transition和touch-action: manipulation;:focus依赖可聚焦元素,须处理outline;nth-child等伪类严格按dom结构匹配。

伪类不是“加到HTML模板里”的功能,而是靠CSS选择器实时匹配状态后触发样式重绘——没写对选择器、没引入CSS、或元素不可交互,hover和active就完全不生效。
为什么:hover在HTML模板里死活不触发
最常见原因是元素默认不可交互:<div>、<code><span></span>这类非表单/链接元素,浏览器不会主动监听其悬停事件,除非显式声明可交互行为。
- 必须加
cursor: pointer,否则用户看不出能悬停,且部分旧版浏览器(如IE11)会跳过渲染 - 移动端 Safari 和 Chrome 对
:hover支持极弱——手指轻点不会触发,需配合@media (hover: hover)做降级处理 - 如果模板用构建工具(如Vite、Webpack)打包,确认 CSS 文件被正确
<link>引入,而非仅内联在<style></style>里但被作用域隔离(如 Vue 的scoped)
:active点击反馈为何一闪而过或根本没反应
:active 只在鼠标按下/手指按住的瞬间生效,松开立即还原。它不是“点击后保持状态”,这点和 JS 的 class 切换有本质区别。
- 必须搭配
transition使用,否则变化像闪烁;例如background-color 0.2s比直接写background-color: #ff5722更自然 - 移动端需额外加
touch-action: manipulation,否则 iOS Safari 会延迟约 300ms 才触发:active - 若目标是“点击后持久高亮”,不能只靠
:active,得用input[type="checkbox"] + label配合:checked,或改用 JS 控制 class
如何用:focus替代JS实现表单焦点反馈
:focus 是原生可聚焦元素(input、textarea、button、带 tabindex 的元素)获得键盘或鼠标焦点时的唯一可靠钩子。
- 记得加
outline: none,否则浏览器默认虚线框会和自定义样式冲突;但要同步补上box-shadow或border,否则键盘用户无法感知焦点位置 -
input:valid和input:invalid依赖 HTML5 表单验证属性(如required、type="email"),不写这些属性,伪类永远不匹配 - Firefox 对
:focus-within支持良好,可用于父容器整体高亮(比如整个表单项区域随任一子 input 获焦变色)
nth-child和not伪类组合时容易忽略的结构陷阱
伪类匹配严格依赖 DOM 树结构,不是“看起来第几个”,而是“在父元素下同级子元素中的真实序号”。
-
tr:nth-child(odd)匹配的是<tr> 在 <code><tbody> 下的序号,如果表格含 <code><thead>,第一行 <code><tr> 实际是 <code>:nth-child(1),但属于<thead>,不会被选中 <li> <code>*:not(.ignore)中的*会匹配所有元素,包括文本节点(在某些浏览器中导致意外 margin),应明确写成.container > * -
:first-child和:first-of-type不等价:前者要求是父元素第一个子节点,后者只要求是该类型第一个——混用会导致斑马纹错位或首尾样式丢失
真正卡住人的从来不是伪类语法本身,而是浏览器如何解析 DOM 结构、何时触发重绘、以及移动端与桌面端的底层行为差异。写完记得在真机上点一点,别只靠 DevTools 的 :hover 模拟。











