:focus-within 无反应最常见原因是容器内无可聚焦元素;仅当子树中元素获焦(如tab键导航或js调用.focus())时才触发,需确保含、等默认可聚焦元素或显式设置tabindex="0"。

为什么 :focus-within 完全没反应
最常见原因是容器内部压根没有可聚焦元素——:focus-within 不是监听“鼠标悬停”或“点击”,它只在**子树中某个元素获得焦点(focus)时才触发**。如果里面全是 <div>、<code><p></p> 这类默认不可聚焦的元素,样式永远不会生效。
检查方法:打开浏览器开发者工具,选中容器内任意子元素,看右下角“Computed”面板里是否显示 tabindex 值为 0 或正整数;或者手动按 Tab 键,看焦点能否进入该元素。
- 默认可聚焦的元素只有:
<a href></a>、<button></button>、<input>、<select></select>、<textarea></textarea>、<summary></summary> <div>、<code><span></span>、<li>等必须显式加tabindex="0"才能被聚焦- 加了
tabindex="-1"的元素只能用 JS 主动.focus(),不能靠 Tab 键到达,但依然能触发:focus-within -
tabindex="0":元素参与标准 Tab 顺序,最常用 -
tabindex="1"或更大:强制插入 Tab 顺序靠前位置,容易打乱可访问性流,慎用 -
tabindex="-1":不能通过 Tab 进入,但可用 JS 调用.focus(),此时仍会激活父容器的:focus-within - 不写
tabindex或设为-2及更小:完全不可聚焦,不会触发:focus-within
tabindex 设成多少才有效
tabindex 的值直接决定元素能否被键盘聚焦,也影响 :focus-within 是否触发:
示例:想让卡片点击后高亮边框,又支持键盘导航
立即学习“前端免费学习笔记(深入)”;
<article class="card">
<h3>标题</h3>
<p>内容</p>
<button tabindex="0">操作</button>
</article>
.card:focus-within {
outline: 2px solid #007bff;
}
JavaScript 主动聚焦却没触发 :focus-within
有时你调用了 element.focus(),但父容器样式还是没变——大概率是聚焦目标不是容器的**后代元素**,而是平级或外部节点。
- 确保
.focus()调用在容器内部的元素上,比如card.querySelector('button').focus(),而不是card.focus() - 如果用
tabindex="-1"给容器自己加了聚焦能力,那触发的是card:focus,不是:focus-within - 动态插入的内容(如 Vue/React 渲染后),需确认 DOM 已挂载完成再调用
.focus(),否则聚焦无效
调试技巧:在控制台执行 document.activeElement,看当前焦点是否落在你预期的子元素上。
兼容性与 SSR 场景下的失效
:focus-within 在 Chrome 60+/Firefox 61+/Safari 15.4+ 支持良好,但仍有两个隐蔽坑点:
- 服务端渲染(SSR)页面首次加载时,若焦点逻辑依赖客户端 JS,而 CSS 已提前注入,
:focus-within无法“预生效”——它纯属运行时行为,没有 JS 就永远不触发 - 某些旧版 Safari(如 iOS 15.0–15.3)对
tabindex="-1"元素触发:focus-within表现不稳定,建议优先用tabindex="0" - 使用 Shadow DOM 时,
:focus-within不跨 shadow boundary,即宿主元素不会响应内部 slot 中聚焦事件
真正容易被忽略的是:这个伪类不支持“模拟聚焦”——哪怕你用 element.focus({preventScroll: true}),只要元素没出现在可访问性树里(比如 display: none 或 visibility: hidden),它照样不工作。










