:focus-within必须写在父容器上才生效,它是为监听子元素获得焦点而设计的伪类,不能用于input等叶子节点;正确用法是作用于form、fieldset或添加tabindex="-1"的div等可聚焦容器。

:focus-within 必须写在父容器上才生效
它不是 :focus 的替代品,而是专为“监听者”设计的伪类。把 :focus-within 加在 <input> 上永远不触发——浏览器直接忽略,因为叶子节点无法监听自身。真正要高亮整个表单组(比如一个 <div class="form-group">),必须把这个伪类写在包裹它的容器上。
<p>常见错误写法:<code>.input:focus-within 或 input:focus-within;正确写法是:.form-group:focus-within 或 fieldset:focus-within。
- 语义化标签如
<form></form>、<fieldset></fieldset>天然可聚焦,直接加:focus-within就行 - 普通
<div> 需显式加 <code>tabindex="-1"(仅一次,不干扰 tab 顺序) - 别给整个
<form></form>加,否则点提交按钮也会触发,容易误高亮 - ✅ 推荐:
<div class="form-group" tabindex="-1"> <li>❌ 错误:<code><div class="form-group">(没任何聚焦能力) <li> <code><label></label>和<input>必须构成祖先-后代关系(<label><input></label>或<label for="x"></label><input id="x">),否则点击 label 不会触发 - 别在
:focus-within规则里改height、margin或display——表格中<tr> 高度变化会导致整行重绘 <li>优先用 <code>outline: 2px solid #007bff:不占空间、无重排、键盘导航友好 - 要用阴影,选
box-shadow: 0 0 0 2px rgba(0,123,255,0.25),别加inset,否则往里缩盖住文字 - 务必统一所有相关元素的
box-sizing: border-box,避免padding+border导致宽度溢出 - 验证方法:在控制台运行
document.activeElement,点击输入框后看返回值是否为预期的原生<input> - 降级方案:用 JS 监听
focusin/focusout并手动切换 class,尤其注意shadow DOM中焦点穿透问题 - React/Vue 自定义组件中,确保原生
<input>是可聚焦的,且没被tabindex="-1"或pointer-events: none拦住
父容器必须能参与焦点流,否则伪类无效
:focus-within 不要求父容器被 tab 进去,但它必须处于“可聚焦上下文”中。纯 <div> 默认不可聚焦,<code>:focus-within 永远不会计算。
高亮样式怎么写才不翻车
很多“失效”其实是样式副作用导致的:边框错位、内容被遮盖、整行跳动。视觉反馈要明显,但不能破坏布局或引发重排。
Safari 旧版本和 IE 兼容性问题
Chrome 65+、Firefox 61+、Safari 15.4+ 均支持,但 Safari 15.3 及更早版本不支持,IE 完全不支持。如果项目需兼容这些环境,不能只靠 :focus-within。
<input> 被封装层拦截或父容器没盒模型,效果就出不来。











