通过编程方式应用焦点时,父元素的 :has() 选择器不会触发 :focus-visible

前端开发 2026-07-11

:has(:focus-visible) 在程序化调用时与 .focus() 不匹配

当以编程方式调用 .focus() 时,:focus-visible 选择器在按钮上并不像在输入元素上那样生效;不过手动通过Tab键将焦点切换到按钮元素时却能生效。最小可复现示例:

document.querySelector('#trigger-button').addEventListener('click', () => {
  document.querySelector('#button').focus();
});
document.querySelector('#trigger-input').addEventListener('click', () => {
  document.querySelector('#input').focus();
});
div {
  border: 1px solid black; 
  margin: 10px 0;
}
div:has(:focus-visible) {
  border: 2px solid red;
}
<button id="trigger-button">Focus Button</button>
<button id="trigger-input">Focus Input</button>
<div>
  <button id="button">Button</button>
</div>
<div>
  <input id="input">
</div>

将焦点通过Tab键切换到 #button 时,会应用 div 边框。点击“Focus”则不会。为什么在通过编程方式触发焦点时,:focus-visible 不会生效?

解决方案

如果在 focus() 上设置 [focusvisible] 选项,它就能生效。这是一个实验性功能。

document.querySelector('#trigger').addEventListener('click', e => {
  document.querySelector('#target').focus({focusVisible: true});
});
div:has(:focus-visible) {
  border: 2px solid red;
}
<button id="trigger">Focus</button>
<div>
  <button id="target">Target</button>
</div>
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章