:focus-within必须写在父容器上才生效,因其设计目标是让父级感知后代焦点;若加在input等子元素自身则永不触发,而父容器内只要有可聚焦子元素(如input、textarea)获焦,样式即自动生效。

为什么:focus-within写在父容器上才生效
因为 :focus-within 的设计目标就是让父级“感知”后代焦点,它不是 :focus 的替代品。你把它加在 <input> 上,浏览器根本不会匹配——<input> 自身用 :focus 就够了。
真正要高亮整块区域(比如一个 <div class="form-group">),必须把 <code>:focus-within 写在那个 <div> 上。只要它内部有可聚焦子元素(<code><input>、<textarea></textarea>、<button></button>、或带 tabindex="0" 的元素),且焦点真能落到它们身上,样式就自动触发。
- 检查 DOM:打开 DevTools,手动点击输入框,看焦点是否落在预期的原生
<input>上,而不是外层<div> <li>React/Vue 组件里容易出问题:如果 <code><myinput></myinput>渲染后内部<input>没透传tabIndex或被tabindex="-1"拦住,:focus-within就查不到活跃后代 -
<label></label>点击能触发,前提是for和id正确配对,且<input>是<label></label>的后代(直接或嵌套均可) - 父容器是纯文本节点或没盒模型(比如没设
display、padding、border),样式改了也看不见 - 子
<input>被套了一层不可聚焦的<div>,而该 <code><div> 有 <code>visibility: hidden、display: contents或pointer-events: none,浏览器无法确认焦点归属 - 用了
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“失灵”
不是写了就一定有效。失效几乎都源于焦点链断裂或渲染上下文缺失:
怎么写高亮样式才不翻车
视觉反馈要明显,但不能破坏布局或干扰键盘导航:
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
兼容性与降级的关键细节
Chrome 65+、Firefox 61+、Safari 15.4+ 都支持,但 IE 完全不支持——这点在企业内网项目中极容易被忽略。
如果必须兼容 IE 或旧版 Safari,不能只靠 :focus-within;得用 JS 监听 focusin/focusout 并手动切换 class。另外,:focus-within 在 :has() 内部可用(如 div:has(input:focus-within)),但反过来不行,别写成 input:focus-within。
最常被漏掉的是:父容器本身虽无需 tabindex,但它必须是可渲染的盒子;若被 display: none 或 visibility: hidden 阻断,伪类照样不生效。










