:focus-within 能检测容器内任意可聚焦子元素是否获焦,无需 js;但子元素必须真正可聚焦,如被 pointer-events: none、contain: layout、tabindex="-1" 或 disabled 等阻止则失效。

:focus-within 能直接检测容器内任意可聚焦子元素是否获得焦点,无需 JS,但必须确保子元素真能拿到焦点,否则它永远不触发。
子元素必须实际可聚焦,不是“看起来像能点”
常见失效场景是:input 被 pointer-events: none 挡住、父层加了 contain: layout、或子元素本身 tabindex="-1" 或 disabled。这些都会让浏览器判定“焦点没进入”,:focus-within 就不会匹配。
-
input、textarea、button、select默认可聚焦;div、span等非表单元素需显式加tabindex="0" - 避免在祖先链上设置
contain: layout或contain: paint,某些 Chrome/Firefox 版本会截断焦点传播 - 移动端 Safari 15.4–16.3 对
input[type="search"]+overflow: hidden组合有 bug,建议降级为监听focusin
:focus-within 匹配的是整个祖先链,不是只限直系父元素
如果 HTML 是 <form><div class="card"><div class="field"><input></div></div></form>,那么点击 input 时,form:focus-within、.card:focus-within、.field:focus-within 全部生效——不是只有最近一层父容器。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 这能用来做嵌套菜单展开(如外层
.dropdown+ 内层.dropdown-menu同时响应) - 但要注意样式优先级:若
.field:focus-within input和input:focus冲突,后者权重更高,可能覆盖前者 - 不要误以为
.card:focus-within只在.card自身被 Tab 进去时才触发——它只看后代有没有焦点
和 JavaScript 的 focusin 事件不是一回事,别混用
:focus-within 是纯 CSS 状态,由浏览器同步维护;focusin 是事件,能捕获脚本调用的 element.focus(),但需要手动绑定、清理,且存在冒泡被阻止的风险。
- 仅改样式(边框、背景、阴影)→ 无条件选
:focus-within,零成本、无内存泄漏、天然支持键盘导航 - 要记录埋点、清空其他区域错误提示、或控制第三方组件 → 必须用
focusin监听在容器上,再用event.target判断是不是你关心的子元素 - 混用风险:比如 JS 主动
input.focus()后立刻读getComputedStyle(container).borderColor,Safari 15.6 下可能有 1 帧延迟,值还是旧的
最易被忽略的一点::focus-within 不关心焦点“怎么来”,只认“有没有”。鼠标点、Tab 进、JS 调用 focus(),它都响应。但它也极度诚实——子元素只要没真正进入焦点管理树(哪怕只是被 visibility: hidden 遮住),它就沉默到底。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










