:focus-within在IE和旧Safari中不生效,因IE全系及Safari 15.3及更早版本未实现该伪类,解析器直接忽略;需用focusin/focusout事件监听并切换class降级兼容,同时注意tabindex、DOM就绪及移动端特定bug。

为什么:focus-within在IE和旧Safari里压根不生效
因为IE全系(包括Edge 12–18)根本不识别:focus-within语法,解析器直接忽略整条规则;Safari 15.3及更早版本也缺失支持。这不是“样式没写对”,而是浏览器压根没实现这个伪类——CSS文件里出现:focus-within,它们就当没看见。
用focusin事件模拟:focus-within的最小可行方案
监听父容器的focusin(不是focus,它不冒泡),手动加class触发样式响应:
const formGroup = document.querySelector('.form-group');
formGroup.addEventListener('focusin', () => {
formGroup.classList.add('focused');
});
formGroup.addEventListener('focusout', () => {
formGroup.classList.remove('focused');
});
对应CSS只需写.form-group.focused label这类规则,完全复刻:focus-within行为。注意两点:
-
focusin事件会冒泡,所以监听在父容器上就能捕获所有子元素获得焦点的时刻 - 不要用
focus和blur——它们不冒泡,得给每个子元素单独绑定,维护成本翻倍
兼容性补丁里最容易漏掉的三个细节
实际部署时,以下三点常导致JS方案“看起来生效了,但键盘用户卡住”:
- 没处理
tabindex="-1"元素:某些自定义组件靠.focus()激活,但focusin仍能捕获,无需额外逻辑 - 忘记移除class的时机:用
focusout而非blur,否则当焦点移到同级其他表单组时,class残留 - SSR或动态渲染场景下,DOM可能还没挂载完就执行JS——加个
document.readyState === 'complete'判断,或用DOMContentLoaded包裹
要不要保留:focus-within原生写法
要。现代浏览器优先走CSS原生路径,JS只做降级兜底:
.form-group:focus-within label { color: #007bff; }
.form-group.focused label { color: #007bff; }
这样既不用删原有CSS,也不用为老浏览器写两套样式。真正麻烦的是移动端Safari 15.4–16.3那个input[type="search"] + overflow: hidden的组合bug——它连:focus-within都触发不了,必须无条件走JS路径,这点容易被忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











