:focus-within必须写在父容器上才生效,因其设计目标是让父级感知后代焦点,而非替代:focus;若加在input等子元素上则永不触发,只有包裹input的.form-group或label等容器应用该伪类,且内部子元素需真实获焦、焦点链未被tabindex="-1"或pointer-events:none等阻断。

为什么:focus-within必须写在父容器上才生效
因为它的设计目标不是替代 :focus,而是让父级“感知”后代焦点。你给 <input> 加 :focus-within,浏览器根本不会匹配——它只在祖先元素上起作用。真正要高亮整个 .form-group 或 <label></label> 区域,就得把 :focus-within 写在那个包裹容器上。
常见错误现象:<div class="form-group"><input></div> 里写了 .form-group:focus-within { border: 2px solid blue; } 却没反应,大概率是子 <input> 被套了不可聚焦的 wrapper,或者被 tabindex="-1" 或 pointer-events: none 拦住了。
- 检查 DevTools 中点击输入框后,焦点是否真落在
<input>上(而非外层<div>) <li>React/Vue 组件中,确保自定义 <code><myinput></myinput>渲染出的原生<input>没被透传tabIndex阻断 -
<label></label>点击能触发的前提是:正确配对for/id,且<input>是其后代(直接或嵌套均可) - 父容器是纯文本节点,或没有盒模型(比如没设
display、padding、border),改了样式也看不见 - 子
<input>外层套了visibility: hidden、display: contents或pointer-events: none的<div>,浏览器无法确认焦点落点 <li>用了 <code>contenteditable的<div> 却没显式加 <code>tabindex="0",旧版 Firefox 可能不触发 - 在 Shadow DOM 内使用时,
:focus-within必须写在 shadow host 上,且子元素焦点需能穿透出来 - 别在
: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,否则会往里缩盖住文字 - 背景色微调可以,但避免
background-color: transparent这类可能被继承覆盖的写法,明确写死值
哪些结构会让:focus-within“失灵”
失效几乎都源于焦点链断裂或渲染上下文缺失,不是兼容性问题,而是 DOM 结构或样式干扰了浏览器对“焦点归属”的判断。
怎么写高亮样式才不翻车
视觉反馈要明显,但不能破坏布局、引发重排,更不能干扰键盘导航体验。
兼容性和降级的关键细节
Chrome 65+、Firefox 61+、Safari 15.4+ 都支持,但 IE 完全不支持——这点在企业内网项目中容易被忽略。
如果必须兼容 IE,不能只靠 :focus-within;得用 JS 监听 focusin/focusout 并手动切换 class。另外注意::focus-within 在 :has() 内部可用(如 div:has(input:focus-within)),但反过来不行,别写成 input:focus-within。
最常被忽略的一点是:父容器本身无需可聚焦(不用设 tabindex),但它内部必须有**真实可聚焦的子元素**,且焦点路径不能被任何样式或属性意外截断。











