Вёрстка модальных окон

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

Новые модальные окна

Новые модальные окна имеют очень простой синтаксис HTML:

<dialog open>Это модальное окно</dialog>

Для отображения модального окна, необходимо добавить атрибутopen

К сожалению, обойтись совсем без JavaScript здесь невозможно, поэтому далее я приведу пример кода, который минимизирует ваше взаимодействие с JavaScript.Мы можем использовать DATA-атрибуты для задания идентификатора модального окна, которое будет перехватываться JavaScript. Работать с этим просто:

<dialog data-modal="my-first-modal">
  <button class="close">×</button>
</dialog>

<button data-modal-open="my-first-modal">Показать модальное окно</button>

Здесь, в атрибутеdata-modal, мы задаем идентификатор модального окна. А далее, в кнопке, позволяющей показать модальное окно, используя атрибутdata-modal-open, мы говорим, что эта кнопка показывает модальное окно с нашим идентификатором.

Простое решение может выглядеть примерно так:

Запустить пример

Стилизация

Модальное окно, открытое с помощьюdialog.openModal(), имеет псевдо-элемент::backdrop. Этот элемент является подложкой под модальным окном и растянут на весь экран. Обычно этот элемент красят в прозрачно-чёрный цвет и добавляют к нему backdrop-filter. Этот набор фильтров позволяет, например, размыть всю страницу кроме модального окна для создания акцента на окно.

Кроме того, можно добавить эффект появления модального окна. Для этого можно добавить немного CSS-кода:

dialog {
  animation: fadeIn 250ms ease-in-out;
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

Этот код позволит модальному окну плавно появляться на экране.

Рассмотренный выше способ в 2019 году работает далеко не во всех браузерах. Поддержку этого способа браузерами можно посмотреть здесь: Can i use Dialog element?

Универсальные модальные окна

Что делать, если нужно поддерживать большее количество браузеров? Выход один - использовать старые методы. Код будет не так изящен, зато работать будет везде.

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

<div class="modal" data-modal="hello-world">
  <div class="dialog">
    <button class="dialog-close" aria-label="Close modal"></button>
    <section class="dialog-content">

      <h2>Модальное окно</h2>
      <p>Какой-то контент</p>

    </section>
  </div>
</div>

Конечно же, придётся добавить много стилей:

.modal {
  /* Подложка будет занимать 100% площади экрана*/
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100vh;
  z-index: 1000;
  /* Скрываем подложку с модальным окном*/
  display: none;
  /* Overflow позволит нам скроллить модальное окно, если контента в нём будет больше, чем может поместиться на экране */
  overflow-y: auto;
  /* Цвет подложки */
  background: rgba(0, 0, 0, 0.8);
  /* Размытие фона */
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  /* Анимация появления */
  animation: fadeIn 250ms ease-in-out;
  /* Добавляем дополнительные стили */
  align-items: flex-start;
  justify-content: center;
  padding: 5vh 0 10vh;
  /* Через JavaScript мы будем добавлять атрибут open, что должно сделать модальное окно видимым */
}
.modal[open] {
  display: flex;
}
.modal .dialog {
  /* Стилизуем само модальное окно */
  width: 100%;
  max-width: 960px;
  min-height: 100px;
  border-radius: 4px;
  position: relative;
  border: none;
  color: white;
  font-weight: 300;
}
.modal .dialog .dialog-close {
  /* Стилизуем кнопку закрытия модального окна */
  position: absolute;
  top: 0;
  right: 0;
  width: 3em;
  height: 3em;
  background: none;
  border: none;
  cursor: pointer;
  outline: none;
}
.modal .dialog .dialog-close::before,
.modal .dialog .dialog-close::after {
  content: "";
  display: block;
  position: absolute;
  top: 50%;
  right: 5px;
  left: 5px;
  border-bottom: 1px solid white;
  transform: rotate(45deg);
}
.modal .dialog .dialog-close::after {
  transform: rotate(-45deg);
}
.modal .dialog .dialog-close:focus::before,
.modal .dialog .dialog-close:hover::before,
.modal .dialog .dialog-close:focus::after,
.modal .dialog .dialog-close:hover::after {
  border-color: tomato;
}
.modal .dialog .dialog-content {
  /* Дополнительные стили для контента*/
  padding: 2em;
  background-color: rgba(0, 0, 0, 0.6);
  border: none;
}
/* Анимация появления*/
@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

Далее сложно: JavaScript. Чтобы уменьшить количество вашего взаимодействия с JavaScript, был снова сделан модуль, работающий через DATA-атрибуты. Всё, как и в предыдущий раз. С ним можно ознакомиться в коде примера:

Запустить пример

Не изобретай велосипед

Часто, лучшим способом является не создание собственного "велосипеда", а использование уже готового продукта. Модальные окна здесь не исключение.Можно просто найти хороший модуль модальных окон, прочитать к нему документацию и использовать его. Тогда практически не придется задумываться насчёт JavaScript и вёрстки окна. Примером могут послужить Tingle или Micromodal.