:focus-within必须写在包裹<input>的父容器上且容器需有可聚焦上下文(如tabindex="-1"),因<input>是叶子节点无法作为:focus-within主体,纯<div>默认不可聚焦导致伪类失效,语义化标签如<form>天然支持,但需避免误触发和布局变动。

直接结论:必须把 :focus-within 写在包裹 <input> 的父容器(如 <div class="form-group">)上,且该容器需具备可聚焦上下文(比如加 tabindex="-1"),否则样式永不生效。
为什么 .input:focus-within 永远不触发
因为 :focus-within 不是 :focus 的替代品,它是专为“监听者”设计的伪类——只在祖先元素上起作用。浏览器会直接忽略 .input:focus-within 这类写法,<input> 是叶子节点,没有后代可监听。
-
<input>自身永远无法成为:focus-within的匹配主体 - 写在
<input>上等同于没写,DevTools 里也看不到匹配高亮 - 真正要响应输入框获焦,目标必须是它的父级容器(
<div>、<label>、<fieldset>等)
父容器没加 tabindex="-1" 就失效
纯 <div> 默认不可参与焦点流,:focus-within 规范要求父容器处于“可聚焦上下文”中——不是说它得被 tab 进去,而是它得能感知后代焦点。
- ✅ 正确:
<div class="form-group" tabindex="-1"><input></div>——tabindex="-1"仅一次,不干扰 tab 顺序 - ❌ 错误:
<div class="form-group"><input></div>—— 容器无聚焦能力,伪类永不计算 - 语义化标签如
<form>、<fieldset>天然支持,无需额外加tabindex - 别给整个
<form>加:focus-within,点任意按钮也会触发,容易误高亮
高亮样式一改 margin 或 height 就翻车
视觉反馈要明显,但不能引发重排或跳动。很多实际项目里翻车,就是因为 :focus-within 规则里动了布局属性。
立即学习“前端免费学习笔记(深入)”;
- 避免在
:focus-within中修改margin、height、display、visibility - 优先用
outline: 2px solid #007bff:不占空间、无重排、键盘导航友好 - 要用阴影,选
box-shadow: 0 0 0 2px rgba(0,123,255,0.25),别加inset,否则往里缩盖住内容 - 确保所有相关元素统一
box-sizing: border-box,否则边框变宽时容器尺寸突变
真正容易被忽略的是焦点链完整性:哪怕结构看着对,只要子元素被 tabindex="-1"、pointer-events: none 或 display: contents 隔断,:focus-within 就静默失效——得进 DevTools 看焦点是否真落在 <input> 上,而不是外层 <div>。


















