FocusOut/Blur 当离开 div 元素时

FocusOut/Blur when leaving div with elements

有一个固定的 div,其中包含一些在用户单击按钮时显示的链接。 出于可访问性目的,我想在失去键盘焦点时关闭此 div,但我找不到要处理的正确 DOM 事件。

我已经尝试了 blurfocusout 事件,但即使子元素仍然具有焦点,它们也会被触发。

示例:

function openMenu() {
  var menu = document.getElementById("menu");
  menu.setAttribute("open", "");
  menu.addEventListener("focusout", handleMenuFocusOut);
  menu.focus();
}
function closeMenu() {
  var menu = document.getElementById("menu");
  menu.removeAttribute("open");
}
function handleMenuFocusOut() {
  console.log("Event triggered!");
  menu.removeEventListener("focusout", handleMenuFocusOut);
  closeMenu();
}
#menu {
  display: none;
  position: fixed;
  top: 50px;
  padding: 20px;
  background-color: gray;
}
#menu[open] {
  display: block;
}
#menu:focus, a:focus {
  background-color: cyan;
}
<div>
  <button onclick="openMenu()">Click Me</button>
  <div id="menu" tabindex="0">
    <ul>
      <li><a href="#">Link 1</a></li>
      <li><a href="#">Link 2</a></li>
      <li><a href="#">Link 3</a></li>
    </ul>
  </div>
  <input type="text"/>
</div>

要重现案例,请单击按钮并按 Tab 键在链接之间导航。 预期的行为是仅在关注文本框等外部元素时关闭 div。

好的,我已经完全改变了这个答案。

您可以使用纯 CSS 使用 focus-within~(用于在打开按钮获得焦点时显示菜单。

看看这个不使用 JS 的片段:

#menu {
  display: block;
  position: fixed;
  top: 50px;
  padding: 20px;
  background-color: cyan;
  opacity: 0;
  pointer-events: none;
}
*:focus { outline: 3px solid #ff0; }
#menu:focus-within, #open-btn:focus ~ #menu {opacity: 1; pointer-events: all;}
<div>
  <button id="open-btn">Click Me</button>
  <div id="menu" tabindex="0">
    <ul>
      <li><a href="#">Link 1</a></li>
      <li><a href="#">Link 2</a></li>
      <li><a href="#">Link 3</a></li>
    </ul>
  </div>
  <input type="text" />
</div>