:focus-within必须写在父容器上,子元素必须真实可聚焦才能触发;它不是:focus的增强版,而是专为监听后代焦点的容器设计的伪类。

:focus-within 必须写在父容器上,子元素必须真实可聚焦,否则它根本不会触发。
为什么 .input:focus-within 永远不生效
很多人把 :focus-within 加在 input、textarea 自身上,结果样式完全没反应。这不是浏览器问题,而是语义错误——:focus-within 不是 :focus 的增强版,它是专为“监听者”设计的伪类,只对**有后代可聚焦**的容器有意义。
- 正确写法是加在包裹层上,比如
.form-group:focus-within或.card:focus-within -
input自身用:focus就够了;想让它影响父级,就必须让父级“听”到它聚焦 - 纯
<div> 默认不可聚焦,但只要内部有可聚焦子元素,它就能响应 <code>:focus-within哪些子元素能真正触发 :focus-within
浏览器只认“此刻有没有焦点”,不是“能不能被聚焦”。只有当前获得键盘或鼠标焦点的元素,才会激活祖先的
:focus-within。- 原生可聚焦元素:
input、textarea、select、button、带href的a - 显式可聚焦元素:设置
tabindex="0"的div、span等 - 无效情况:
tabindex="-1"且未被 JS 显式调用.focus();子元素被display: none或visibility: hidden遮盖;父容器用了display: contents(会打断焦点流)
:focus-within 常见写法错误与陷阱
即使语法正确,也容易因细节失效。这些坑比兼容性问题更常导致失败。
- 不要写成
.parent:focus > .child——这是:focus作用于父自身,而父<div> 默认不可聚焦 <li>避免 <code>.card:hover:focus-within这种写法,它表示“同时 hover 且子聚焦”,通常你需要的是“任一满足”,应拆成.card:hover, .card:focus-within -
input上设outline: none且没提供其他视觉反馈,人眼误判“没聚焦”,其实:focus-within已生效 - 深层嵌套时慎用
.card:focus-within *,可能意外覆盖内部按钮、图标等已有样式 - JS fallback 必须监听
focusin和focusout(不是focus/blur),因为前者冒泡,能捕获子元素事件 - 仅给父容器绑定
focus事件,收不到子元素的聚焦信号——这是最常被忽略的逻辑断点 - 若需区分具体哪个子元素聚焦,
:focus-within无能为力,得靠 JS 记录event.target
兼容性与 fallback 方案的关键点
截至 2026 年 9 月,
:focus-within在 Chrome 60+、Firefox 61+、Edge 79+、Safari 15.4+ 均稳定支持,但 iOS 15.4 及更早 Safari 仍缺失,IE 完全不支持。真正难的不是写对选择器,而是确认焦点确实落到了你认为该落的地方——检查
tabindex、display、pointer-events和是否被 JS 中途blur(),比反复改 CSS 更有效。 - 原生可聚焦元素:











