:focus-within只能作用于父容器,触发条件是子元素真实获得焦点,如input、textarea、select、button、tabindex="0"元素或带href的a标签;tabindex="-1"未显式focus、display:none、visibility:hidden或display:contents会阻止触发。

:focus-within 只能写在父容器上,且子元素必须真实可聚焦、焦点链未被阻断,否则永远不触发。
哪些子元素能真正触发 :focus-within
浏览器只认“此刻有没有焦点”,不是“能不能被聚焦”。有效触发源包括:
-
<input>、<textarea></textarea>、<select></select>、<button></button>(原生可聚焦) - 显式设置
tabindex="0"的元素(如<div tabindex="0">) <li> <code><a></a>标签(只要带href属性) -
tabindex="-1"但没被 JS 显式调用.focus() - 子元素被
display: none或visibility: hidden遮盖 - 父容器用了
display: contents,导致焦点落点无法被浏览器识别 - ✅ 正确:
.form-group:focus-within { background: #f0f8ff; }(<div class="form-group"><input></div>) - ❌ 错误:
input:focus-within或div:focus-within(<div> 默认不可聚焦,且不是监听者角色) <li>⚠️ 注意:<code><label></label>和<input>必须构成祖先-后代关系(如<label><input></label>),否则点击 label 不会触发:focus-within - 如果同时写了
input:focus { border: 2px solid red; },它会压过.form-group:focus-within input的边框设置 - 避免写成
.form-group:hover:focus-within——这是交集,不是并集;要“任一满足”请用.form-group:hover, .form-group:focus-within - 深层嵌套慎用通配符,比如
.card:focus-within *,可能意外重置按钮图标等已有样式 - JS fallback 必须用
focusin/focusout(不是focus/blur),因为前者冒泡,能捕获子元素事件 - 仅在父元素上绑定
focus事件收不到子元素信号——这是最常被忽略的逻辑断点 - 若需支持老环境,
tabindex="-1"可让纯<div> 成为可聚焦上下文,但只需一次,不要滥用 </div>
以下情况不会触发:
:focus-within 必须作用于父容器,不能加在子元素上
很多人写了 .input:focus-within 却没反应,是因为伪类设计初衷就是让祖先“监听”后代——它不是 :focus 的替代品。
常见样式冲突和优先级陷阱
.form-group:focus-within input 匹配的是“当父容器处于 focus-within 状态时,其内部的 input”,不是 input 自身获焦。但它容易被更高优先级规则覆盖:
兼容性与 fallback 的关键细节
截至 2026 年 9 月,:focus-within 在 Chrome 60+、Firefox 61+、Edge 79+、Safari 15.4+ 均稳定支持,但 iOS 15.4 及更早 Safari 仍缺失,IE 完全不支持。











