Как сделать модальное окно с помощью javascript

Модальное диалоговое окно должно показываться поверх документа с которым будет запрещено что-либо делать до тех пор, пока диалог не будет завершён и закрыт. Начнём.

HTML разметка

<div class="modal-container"> 
  <div class="modal-content">
    <button class="close">Закрыть</button>
    <p>Много контента для скролла</p>
  </div>
</div>

Контейнер

Начнем с элемента контейнера. Это будет div, растянутый по ширине и высоте документа в браузере поверх всего приложения, чтобы запретить пользователю делать что-либо с контентом в приложении: выделять текст, кликать по кнопкам, ссылкам и т.д.

.modal-container {
  position: fixed;
  left: 0;
  top: 0; 
  display: flex;
  width: 100vw;
  height: 100vh; 
  padding: 30px;
  background-color: rgba(0, 0, 0, 0.5);
}

Добавим position: fixed, чтобы контейнер всегда был в поле зрения.

Для центрирования содержимого модального окна по горизонтали и вертикали будем использовать display: flex; justify-content: center; align-items: center;.

Контент

Теперь элемент для содержимого диалогового окна. Это собственно и есть модальное окно, которое будет располагаться в центре экрана.

.modal-content {
  overflow: scroll;
  width: 100%; 
  height: 100%; 
  max-width: 500px; 
  max-height: 400px; 
  background-color: #fff; 
}

Обратите внимание, что вместо width и height используются max-width и max-height. Это для того, чтобы модальное окно работало и на небольших экранах. Если вместо этого использовать width: 500px;, то на мобильных устройствах будет горизонтальная полоса прокрутки.

модальное окно

Кнопка «закрыть»

Последний шаг для завершения модального окна — это стилизация кнопки для его закрытия. Поместим кнопку в правый верхний угол.

.close {
 position: absolute;
 right: 0;
 top: 0;
 width: 30px;
 height: 30px;
}

Добавление модальной функциональности с помощью Javascript

Модальное окно уже начинает хорошо выглядеть. Следующий шаг — добавление некоторой функциональности, вот наши требования:

  • Должна быть возможность открывать и закрывать окно.
  • Когда модальное окно открыто, нужно отключить прокрутку в родительском приложении.

Выберем интерактивные элементы

Чтобы переключать режим модального окна, начнём с определения интерактивных элементов.

var modal = document.querySelector('.modal-container');
var closeButton = document.querySelector('.close');
var modalTriggers = document.querySelectorAll('[data-trigger]');

Модальное окно не должно отображаться при инициализации приложения. Позаботимся об этом, добавив следующие css-свойства модальному контейнеру.

.modal-container { 
  pointer-events: none; 
  opacity: 0;
}

А также, добавим новый класс, который будет показывать модальное окно.

.modal-container.is-open { 
  pointer-events: all; 
  opacity: 1;
}

Добавим перехватчики событий

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

var openModal = function() {
 modal.classList.add('is-open')
}
var closeModal = function() {
 modal.classList.remove('is-open')
}
modalTriggers.forEach(function(item) { 
 item.addEventListener('click', openModal)
})
closeButton.addEventListener('click', closeModal)

Теперь можно переключать видимость модального окна.

Отключение скролла в родительском приложении

И последнее, но не менее важное: посмотрим, как отключить прокрутку в родительском приложении, когда модальное окно открыто.

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

var isModalOpen = false;
var pageYOffset = 0;
var openModal = function() {
 ...
 isModalOpen = true;
 pageYOffset = window.pageYOffset;
}
var closeModal = function() {
 ...
 isModalOpen = false;
}
var onScroll = function(e) {
 if (isModalOpen) {
  window.scrollTo(0, pageYOffset);
 }
}
document.addEventListener('scroll', onScroll);

Вот и всё!

See this code Modal dialog window on x.xhtml.ru.