:focus-within必须写在能包裹可聚焦子元素的父容器上且该容器需为可聚焦上下文,否则不生效;纯div默认不可聚焦,须加tabindex="-1",并避免display:contents等中断焦点链的样式。

:focus-within 能直接让父容器响应子元素聚焦,但必须写在**能包裹可聚焦子元素的父容器上**,且该容器需处于可聚焦上下文——否则样式永远不会触发。
为什么 .card:focus-within 没反应?
常见错误是只写了 .card:focus-within { ... },但 <div class="card"> 默认不可聚焦,浏览器不认为它属于焦点流。这不是 bug,是规范行为。
- 纯
<div>必须显式加tabindex="-1"才能成为“可聚焦上下文”,从而让:focus-within生效 - 如果卡片里
<input>外层套了display: contents或pointer-events: none的 wrapper,焦点链就断了,伪类失效 - React/Vue 中自定义
<MyInput>组件,若透传了tabIndex="-1"或禁用了pointer-events,也会导致内部<input>实际无法获焦
怎么写才真正高亮整个卡片?
关键不是加多少样式,而是先确保结构和上下文正确。推荐写法:
<div class="card" tabindex="-1"> <h3>登录</h3> <label>邮箱<input type="email"></label> <button type="submit">提交</button> </div>
对应 CSS:
立即学习“前端免费学习笔记(深入)”;
.card {
padding: 16px;
border-radius: 8px;
transition: all 0.2s ease;
}
.card:focus-within {
outline: 2px solid #007bff;
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
}
-
outline和box-shadow不占布局空间,不会引发重排或文字跳动 - 避免在
:focus-within规则里改padding、margin、height,尤其在卡片嵌套或 Grid/Flex 布局中容易撑开错位 - 如果要用背景色,别写
background-color: transparent,明确写死值如#f8f9fa,防止被继承覆盖
哪些结构会让 :focus-within “突然失灵”?
失效几乎都源于 DOM 结构或样式干扰了浏览器对“焦点归属”的判断,而非兼容性问题。
-
<label for="x">和<input id="x">是分离式写法时,外层.card必须带tabindex="-1",否则点击 label 不会触发:focus-within - 卡片内用了
contenteditable的<div>却没加tabindex="0",旧版 Firefox 可能不触发 - 在 Shadow DOM 内使用时,
:focus-within必须写在 shadow host 上,且子元素焦点需能穿透出来 - 父容器是
<span>或空<div>且无盒模型(比如没设padding、border),样式改了也看不见效果
最常被忽略的一点:高亮本身不是目的,确保键盘用户能清晰识别当前操作区域才是核心。用 outline 或外扩 box-shadow 是安全选择;一旦改了布局属性,哪怕只多 1px padding,在某些嵌套结构里也可能盖住文字或错位边框。


















