Як реалізувати подію "клік поза елементом" на чистому JavaScript

Привіт:) У цьому пості покажу як за допомогою JavaScript реалізувати подію "клік поза елементом".

Одним із найпоширеніших завдань у веброзробці є закриття інтерактивних елементів (модальних вікон, випадаючих списків або мобільного меню), коли користувач клікає в будь-якому іншому місці сторінки. Оскільки в JavaScript немає прямої події onclickoutside, ми використовуємо логічну перевірку ієрархії DOM-дерева.

Основний принцип роботи

Суть методу полягає в тому, щоб додати обробник події click на весь документ (document), а потім за допомогою методу .contains() перевірити, чи є ціль кліку (event.target) частиною нашого елемента.

Приклад із квадратним блоком

HTML та CSS:

<div id="wrapper">
  <p>Текст</p>
</div>

<style>
#wrapper {
  width: 100px;
  height: 100px;
  background-color: red;
}
</style>

JavaScript:

// Вибір елементу, за межами якого потрібно відслідковувати клік
let myElement = document.getElementById('wrapper');

document.addEventListener('click', function(event) {
  // Перевіряємо, чи містить наш елемент об'єкт, на який натиснули
  var isClickInside = myElement.contains(event.target);

  if (!isClickInside) {
    console.log('Тут те, що потрібно робити, коли клацнув поза елементом');
  }
});
до змісту ↑

Практичне застосування: закриття мобільного меню

Найчастіше цей прийом використовується для UX-дизайну мобільних інтерфейсів. Наприклад, якщо користувач відкрив меню, він очікує, що воно закриється, якщо він натисне на затемнену область або будь-яку іншу частину сайту.

Реальний кейс

Приховати блок контенту після мобільного меню при кліку поза кнопкою перемикача:

let specifiedElement = document.getElementsByClassName('responsive-menu-toggle')[0];

document.addEventListener('click', function(event) {
  let isClickInside = specifiedElement.contains(event.target);
          
  if (!isClickInside) {
    // Знаходимо блок контенту та приховуємо його
    let menuContent = document.getElementsByClassName('after-mobile-menu-content')[0];
    if (menuContent) {
      menuContent.style.display = 'none';
    }
  }
});

Інші приклади та оптимізація

Використання сучасного методу closest()

Метод .contains() чудовий, але іноді зручніше використовувати .closest(). Він перевіряє, чи є ціль кліку або її батьки відповідними до певного селектора.

document.addEventListener('click', (event) => {
  const menu = document.querySelector('.my-menu');
  
  // Якщо клік був НЕ по меню і НЕ по його дочірніх елементах
  if (!event.target.closest('.my-menu')) {
    menu.classList.remove('active');
  }
});

Важливе зауваження: вплив на продуктивність

Коли ви додаєте слухач подій на весь document, він спрацьовує при кожному кліку на сторінці.

  • Порада. Якщо ваше меню закрите, знімайте обробник події за допомогою removeEventListener, щоб не навантажувати браузер зайвими перевірками, коли в них немає потреби.

Проблема зі спливанням подій (Bubbling)

Якщо ви відкриваєте меню по кнопці, клік по цій самій кнопці може одночасно вважатися "кліком поза меню". Щоб уникнути миттєвого закриття, використовуйте event.stopPropagation() у функції, яка відкриває елемент.

Висновок

Метод .contains() у поєднанні з глобальним обробником подій — це надійний та кросбраузерний спосіб реалізації інтуїтивного інтерфейсу. Це робить ваш сайт зручнішим, дозволяючи користувачам легко скасовувати дії одним кліком.

Михайло Петров
Михайло Петров

Мене звати Михайло. Я — WordPress-розробник. Створюю візитки, корпоративні сайти, інтернет-магазини, блоги на WordPress. Надаю консультації з WordPress.

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *