Home > Mobile >  FocusOut/Blur when leaving div with elements
FocusOut/Blur when leaving div with elements

Time:09-18

There is a fixed div with some links that are shown when user clicks a button. For accessibility purposes, I want to close this div when it loses keyboard focus, but I can`t find the correct DOM event to handle.

I've tried blur and focusout events but they are also triggered even when children elements still has focus.

Example:

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>

To reproduce the case, click the button and press tab to navigate between links. The expected behavior is to close div only when focusing outside elements, like the textbox.

CodePudding user response:

Ok, I've completely changed this answer.

You can do this using pure CSS using focus-within and ~ (which is used to show the menu when the open-button is focused.

Take a look at this snippet which uses no 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>

  • Related