Закрытие по клику вне области

Библиотека Focus-trap предназначена для управления фокусом внутри определённой области DOM, что особенно важно для модальных окон, всплывающих меню и диалогов. Основная задача — предотвратить выход фокуса за пределы указанного контейнера при навигации с помощью клавиатуры, обычно клавиши Tab и Shift+Tab.

Focus-trap создаёт «ловушку» фокуса, автоматически переводя его на первый или последний интерактивный элемент контейнера при попытке покинуть область. Это позволяет обеспечить доступность (accessibility) и корректное взаимодействие с элементами интерфейса.


Настройка ловушки фокуса

Для создания ловушки используется функция createFocusTrap, которой передаётся контейнер и объект конфигурации:

import { createFocusTrap } from 'focus-trap';

const modal = document.getElementById('modal');

const trap = createFocusTrap(modal, {
  escapeDeactivates: true,
  clickOutsideDeactivates: true,
  allowOutsideClick: true
});

Ключевые параметры:

  • escapeDeactivates — позволяет закрыть ловушку при нажатии клавиши Escape.
  • clickOutsideDeactivates — отключает ловушку при клике вне контейнера.
  • allowOutsideClick — позволяет клики по внешним элементам при активной ловушке (часто используется совместно с clickOutsideDeactivates).

Закрытие по клику вне области

Для реализации закрытия модального окна по клику вне области фокуса важен параметр clickOutsideDeactivates.

const trap = createFocusTrap(modal, {
  clickOutsideDeactivates: true
});

document.getElementById('openModal').addEventListener('click', () => {
  trap.activate();
});

При включении этой опции библиотека сама отслеживает клики вне контейнера и деактивирует ловушку.

Если требуется более точное управление — можно использовать функцию обратного вызова onDeactivate:

const trap = createFocusTrap(modal, {
  clickOutsideDeactivates: (event) => {
    return !modal.contains(event.target);
  },
  onDeactivate: () => {
    modal.style.display = 'none';
  }
});

Здесь clickOutsideDeactivates принимает функцию, возвращающую true или false. Это позволяет условно закрывать модальное окно, например, игнорируя клики по определённым элементам вне контейнера.


Сценарии использования

  1. Модальные окна — самый распространённый кейс. Ловушка предотвращает потерю фокуса, обеспечивая доступность для пользователей клавиатуры.
  2. Всплывающие панели и меню — важно, чтобы фокус не уходил на элементы интерфейса за пределами панели до её закрытия.
  3. Диалоги подтверждения — закрытие по клику вне области позволяет пользователю легко отменять действие, сохраняя UX-консистентность.

Обработка кликов с кастомной логикой

В некоторых интерфейсах требуется не просто закрывать модальное окно при клике вне, а выполнять дополнительные действия. Это реализуется через событие click и метод deactivate:

document.addEventListener('click', (event) => {
  if (!modal.contains(event.target)) {
    trap.deactivate();
    console.log('Ловушка фокуса деактивирована кликом вне');
  }
});

При этом clickOutsideDeactivates можно оставить включённым или отключить для большей гибкости.


Советы по интеграции

  • Не блокировать все клики вне. Иногда элементы за модальным окном должны оставаться интерактивными. Использовать allowOutsideClick с условной логикой.
  • Синхронизация с анимациями. Если модальное окно закрывается с анимацией, рекомендуется вызывать trap.deactivate() после окончания анимации, чтобы избежать неожиданного перемещения фокуса.
  • Комбинация с onActivate. При открытии окна полезно автоматически ставить фокус на первый интерактивный элемент, чтобы пользователи клавиатуры могли сразу начать взаимодействие.

Примеры комбинаций

const trap = createFocusTrap(modal, {
  escapeDeactivates: true,
  clickOutsideDeactivates: (event) => {
    return !modal.contains(event.target);
  },
  allowOutsideClick: true,
  onActivate: () => modal.classList.add('active'),
  onDeactivate: () => modal.classList.remove('active')
});

Такая конфигурация обеспечивает полный контроль над фокусом, закрытием модального окна и визуальным состоянием компонента.


Focus-trap сочетает простоту настройки и мощные возможности для управления фокусом. Понимание механизма закрытия по клику вне области позволяет создавать интерфейсы с предсказуемым и удобным поведением, отвечающие требованиям доступности и UX.