Главная » Модальное окно на JavaScript и его модификации

Модальное окно на JavaScript и его модификации


11.06.2021, 21:19
Структура модального окна и принцип его работы

Модальное окно представляет собой изначально скрытое всплывающее окно с какой-либо информацией, его появление на странице блокирует дальнейшую работу и взаимодействие пользователя с остальными элементами на странице, до тех пор, пока пользователь не закроет модальное окно.

Появление модального окна может быть инициировано как самим пользователем (например, при клике на кнопке "Напишите нам" всплывает модальное окно с формой обратной связи), так и автоматически в результате работы скрипта (например, спустя какое-то время после того, как пользователь вошел на сайт, открывается окно с рекламной информацией).

Структура модального окна представляет собой родительский блок-контейнер, внутри которого расположен блок с контентом (содержимое, которое будет показываться в модальном окне при его появлении на странице)

Код

<div class = "modal">
  <div class = "modal__dialog">
  <div class = "modal__content">
  <p>Здесь содержимое модального окна</p>
  </div>
  </div>
</div>

Изначально модальное окно на странице скрыто, для этого в CSS-стилях для его родительского блока должно быть установлено:

Код

.modal {
  display: none;
}

Ниже стили для оформления и позиционирования модального окна:

Код

/* Стили для родительского контейнера (собственно, это и есть подложка, затемняющая всю страницу) */

.modal {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 1050;
  display: none; /* => позволяет изначально скрыть модальное окно */
  width: 100%;
  height: 100%;
  overflow: hidden;
  background-color: rgba(0, 0, 0, .7)
}

/* Стили для контейнера с блоком контента (по-сути, это стили самого модального окна) */

.modal__dialog {
  max-width: 500px;
  margin: 140px auto
}

/* Стили для блока с контентом (блок с информацией внутри модального окна) */

.modal__content {
  position: relative;
  width: 100%;
  padding: 20px;
  background-color: #6ab04c;
  color: #ffffff;
  border-radius: 4px;
}

В коде страницы выбираем (или прописываем, там где необходимо) элемент, с помощью которого будем вызывать появление модального окна, например, кнопку, и чтобы её идентифицировать, зададим ей дополнительно data-атрибут:

Код

<button data-modal>Открыть модальное окно</button>

Базовый скрипт для работы модального окна

Получаем кнопку-триггер со страницы по её data-атрибуту

Код

const modalTrigger = document.querySelector('[data-modal]');

Теперь получим контейнер модального окна:

Код

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

Используя обработчик события для полученной со страницы кнопки, пишем скрипт для открытия модального окна:

Код

modalTrigger.addEventListener('click', () => {
  modal.classList.add('show');
});

Суть работы скрипта: при клике по кнопке-триггеру для родительского блока добавляется класс .show и модальное окно появляется на странице.

Чтобы закрыть модальное окно, сделаем для этого элемент-триггер в виде отдельного блока с крестиком и поместим его в блок с контентом:

Код

  <div class="modal">
  <div class="modal__dialog">
  <div class="modal__content">
  <div class="modal__close" data-close>×</div>
  <p>Это содержимое модального окна</p>
  </div>
  </div>
  </div>

Добавим css-стили для его оформления и позиционирования:

Код

.modal__close {
  position: absolute;
  top: 8px;
  right: 14px;
  font-size: 30px;
  color: #000;
  opacity: .5;
  font-weight: 700;
  border: none;
  background-color: transparent;
  cursor: pointer
}

также в стили добавим два класса, .show и .hide, первый из них мы будем добавлять к контейнеру модального окна для его открытия, второй - для его закрытия

Код

.show {
  display: block
}

.hide {
  display: none
}

Прописываем скрипт для закрытия модального окна, предварительно получив наш "блок-крестик" со страницы по его data-атрибуту:

Код

const modalCloseBtn = document.querySelector('[data-close]');

modalCloseBtn.addEventListener('click', () => {
  modal.classList.add('hide');
  modal.classList.remove('show');
});

Суть работы здесь: при клике на крестик в модальном окне, родительскому контейнеру добавляется класс .hide, а класс .show у него удаляется (модальное окно исчезает)

И так как здесь добавляется класс .hide, то в скрипте открытия модального окна нужно дописать удаление этого класса:

Код

modalTrigger.addEventListener('click', () => {
  modal.classList.add('show');
  modal.classList.remove('hide'); /* добавляем удаление класса .hide */
});

Чтобы при открытом модальном окне не работал скролл страницы сайта, нужно для body добавить свойству overflow значение hidden

Код

modalTrigger.addEventListener('click', () => {
  modal.classList.add('show');
  modal.classList.remove('hide');
  document.body.style.overflow = 'hidden';
});

Для восстановления возможности скролла страницы после закрытия модального окна, в скрипте закрытия модального окна для свойства overflow в качестве значения оставляем пустые кавычки:

Код

modalCloseBtn.addEventListener('click', () => {
  modal.classList.add('hide');
  modal.classList.remove('show');
  document.body.style.overflow = '';
});

Тестируем модальное окно

Открытие-закрытие модального окна можно реализовать также с помощью "переключателя", метода toggle(), контролируя наличие класса .show у контейнера модального окна:

Код

modalTrigger.addEventListener('click', () => {
  modal.classList.toggle('show');
  document.body.style.overflow = 'hidden';
});

modalCloseBtn.addEventListener('click', () => {
  modal.classList.toggle('show');
  document.body.style.overflow = '';
});

Несколько кнопок и общее модальное окно

Как пример: продающий лендинг, в котором есть кнопки в начале, середине и в конце страницы, по клику на любую из них должна открыться форма обратной связи.

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

Как это реализовать?

Допустим, вот три кнопки:

Код

  <button data-modal>Первая кнопка</button>
  <button data-modal>Вторая кнопка</button>
  <button data-modal>Третья кнопка</button>

Получим их со страницы;

Код

const modalTriggers = document.querySelectorAll('[data-modal]');

Мы получили массивоподобную коллекцию, используем метод forEach(), чтобы взаимодействовать с каждой кнопкой в отдельности:

Код

modalTriggers.forEach(btn => {
  btn.addEventListener('click', () => {
  modal.classList.add('show');
  modal.classList.remove('hide');
  document.body.style.overflow = 'hidden';
  });
});

Теперь при клике на любой из этих кнопок, откроется модальное окно.

Закрытие модального окна кликом в любом месте страницы

Чтобы это реализовать, нужно использовать проверку условия: если пользователь кликнул по подложке (а это блок с классом .modal), модальное окно закрываем.

Код

modal.addEventListener('click', (e) => {
  if (e.target === modal) {
  modal.classList.add('hide');
  modal.classList.remove('show');
  document.body.style.overflow = '';
  }
});

Закрытие модального окна при нажатии клавиши ESC на клавиатуре

Код

document.addEventListener('keydown', (e) => {
  if (e.code === 'Escape' && modal.classList.contains('show')) {
  modal.classList.add('hide');
  modal.classList.remove('show');
  document.body.style.overflow = '';
  }
});

Внутри функции проверяется условие, что если нажата клавиша Esc и модальное окно при этом открыто, то выполняется тело функции, модальное окно закрывается.

Автоматическое появление модального окна через заданный интервал времени

Создадим функцию открытия модального окна:

Код

function openModal() {
  modal.classList.add('show');
  modal.classList.remove('hide');
  document.body.style.overflow = 'hidden';
  clearInterval(modalTimerId); /* прописываем на случай, если пользователь сам открыл модальное окно, чтобы потом не открылось еще автоматическое модальное окно */
}

И используем её в setTimeout() для автоматического открытия модального окна через 3 секунды:

Код

const modalTimerId = setTimeout(openModal, 3000);

Автоматическое появление модального окна при пролистывании страницы пользователем до конца

Код

  function showModalByScroll() {
  if (window.pageYOffset + document.documentElement.clientHeight >=   document.documentElement.scrollHeight - 1) {
     openModal();
     window.removeEventListener('scroll', showModalByScroll);
     }
  }

  window.addEventListener('scroll',showModalByScroll);

pageYOffset - количество пикселей по вертикали уже пролистанное пользователем
clientHeight - высота видимой части
scrollHeight - полная высота контента с учетом уже прокрученной части

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

Полезные ссылки:
Узнать коды клавиш

КОММЕНТАРИИ (0)