Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как отследить клик вне элемента

Короткий ответ

Слушайте клики по всему документу и проверяйте через contains(), был ли клик внутри элемента:

<button id="toggle">Menu</button>
<ul id="menu" hidden>
  <li>Profile</li>
  <li>Settings</li>
</ul>
<script>
  const menu = document.getElementById('menu');
  const toggle = document.getElementById('toggle');
 
  toggle.addEventListener('click', () => {
    menu.hidden = !menu.hidden;
  });
 
  document.addEventListener('click', (event) => {
    if (!menu.contains(event.target) && !toggle.contains(event.target)) {
      menu.hidden = true;
    }
  });
</script>

Через closest

closest() находит ближайшего родителя, подходящего под селектор. Это удобно, когда выпадающих меню несколько:

document.addEventListener('click', (event) => {
  if (!event.target.closest('.dropdown')) {
    document.querySelectorAll('.dropdown.open').forEach((el) => el.classList.remove('open'));
  }
});

Клавиша Escape

Пользователи ожидают, что окно закроется и по Escape:

document.addEventListener('keydown', (event) => {
  if (event.key === 'Escape') menu.hidden = true;
});

Частая ошибка

Без проверки кнопки клик по ней открывает меню, а затем тот же клик доходит до документа и сразу его закрывает. Исключите кнопку или остановите событие через event.stopPropagation().

toggle.addEventListener('click', (event) => {
  event.stopPropagation();
  menu.hidden = !menu.hidden;
});

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.