Модальное окно на CSS и чистом JavaScript за три шага

В этой статье разберем, что такое модальное окно, из чего оно состоит, а также создадим пример такого окна с живой демонстрацией.

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

Модальное окно (всплывающее окно, поп-ап) представляет собой элемент интерфейса в виде блока с контентом, который появляется над всем остальным содержимым страницы.

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

Обычно модальное окно состоит из следующих элементов:

  • Tекст с уведомлением, уточнением, предупреждением либо другой информацией, которая требует реакции пользователя, прежде чем он продолжит работать с сайтом. Например, если сайту необходимо уточнить, действительно ли пользователь хочет удалить свой профиль из системы либо он нажал кнопку удаления по ошибке. В этом случае текст может быть таким: «Вы действительно хотите удалить свой профиль? Действие не может быть отменено!».
  • Другие элементы, дополняющие текст, например, таймер обратного отсчета.
  • Элементы взаимодействия с модальным окном. К примеру, для закрытия окна — «крестик» в верхнем углу блока либо кнопка «Отмена». Если всплывающее окно является просто информационным, то закрыть окно можно с помощью кнопки «OK». Пользователю также может быть предложено совершить запрашиваемое действие, нажав на определенную кнопку. Например, на поп-апе с рекламной акцией можно увидеть кнопку «Купить!».

Разберем, как же создать такой элемент интерфейса, как модальное окно.

Описание примера

В качестве примера создадим всплывающее окно с подпиской на рассылку. Окно будет открываться после нажатия на кнопку «Подписаться». Содержимое поп-апа будет включать в себя заголовок, поле для ввода email с текстом, предлагающим заполнить это поле, а также две кнопки: для подтверждения подписки и для закрытия окна.

Наша работа будет включать несколько этапов:

  • Верстка содержимого окна.
  • Размещение поп-па над контентом страницы и добавление тени.
  • Добавление интерактивности (открытие/закрытие окна, имитация подписки после нажатия на кнопку «Подписаться» в открытом окне).

Результат вы сможете увидеть, нажав на кнопку «Подписаться» в конце статьи.

Верстка содержимого модального окна

Начнем с верстки содержимого поп-апа. Сделаем форму с полем для ввода электронного адреса и двумя кнопками — «Подписаться» и «Закрыть». Сверху добавим заголовок. В тегах input разместим идентификаторы — они нам понадобятся для работы с JavaScript.

HTML:

<form id="demoModal" class="demoModal">
    <h2>Подписка на рассылку</h2>
    <div id="demoModalInfo" class="demoModal__info">
        <label for="email">Введите ваш email для подписки на нашу рассылку:</label>
        <input type="email" name="email" id="email" placeholder="your@email.com" required>
    </div>
    <div class="demoModal__actions">
        <input type="submit" id="demoModalSubscribe" class="demoModal__button active" value="Подписаться">
        <input type="button" id="demoModalClose" class="demoModal__button close" value="Закрыть">
    </div>
</form>

CSS:

.demoModal {
    padding: 20px;
    width: 320px;
    background-color: #393939;
    box-shadow: 0 0 10px 0 #fff;
    border-radius: 10px;
    z-index: 1000;
    text-align: center;
}

.demoModal h2 {
    color: #00c1c5;
    font-size: 1.3em;
}

.demoModal label {
    color: #fff;
    font-size: 0.9em;
    margin-bottom: 0.1em!important;
}

.demoModal__info {
    margin-top: 0.7em;
    color: #fff;
}

.demoModal input[type='email'] {
    width: 100%;
    font-size: 1.2em;
    box-sizing: border-box;
    border: 1px solid #ccc;
    border-radius: 5px;
    padding: 10px;
    margin-top: 0.6em;
}

.demoModal__actions {
    margin-top: 0.8em;
}

.demoModal__button {
    padding: 5px 10px;
    color: #fff;
    background-color: transparent;
    border: 2px solid #fff;
    cursor: pointer;
    font-size: 16px;
    border-radius: 5px;
    margin: 10px;
    transition: all .3s;
}

.demoModal__button.active {
    background-color: #00c1c5;
}

.demoModal__button.active:hover {
    color: #00c1c5;
    background-color: #fff;
}

.demoModal__button.close {
    color: #393939;
    background-color: #ccc;
}

.demoModal__button.close:hover {
    background-color: #a9a9a9;
}

Результат будет выглядеть следующим образом:

Подписка на рассылку

У нас есть стилизованный блок с формой подписки с пока не работающими кнопками. Далее мы создадим для этого блока тень и разместим его в центре над всей страницей.

Расположение модального окна поверх страницы

Для создания затемнения под выпадающим окном и его центрирования обернем нашу форму в блок div. Размещение окна по центру получим, благодаря flexbox, задав обертке правила центрирования содержимого (display: flex; justify-content: center; align-items: center;). А, используя фиксированное позиционирование (position: fixed; top: 0; left: 0;), установку ширины и высоты обертки на максимальные значения (width: 100%!important; height: 100%!important;) и указав большой размер свойства z-index (z-index: 99999;) мы добьемся, чтобы весь поп-ап с тенью разместился над контентом страницы. По умолчанию модальное окно с тенью будет скрыто — для этого мы добавим display: none; для обертки.

HTML после добавления обертки выглядит так:

<div id="demoModalShadow" class="demoModalShadow">
    <form id="demoModal" class="demoModal">
        <h2>Подписка на рассылку</h2>
        <div id="demoModalInfo" class="demoModal__info">
            <label for="email">Введите ваш email для подписки на нашу рассылку:</label>
            <input type="email" name="email" id="email" placeholder="your@email.com" required>
        </div>
        <div class="demoModal__actions">
            <input type="submit" id="demoModalSubscribe" class="demoModal__button active" value="Подписаться">
            <input type="button" id="demoModalClose" class="demoModal__button close" value="Закрыть">
        </div>
    </form>
</div>

Дополним CSS для стилизации обертки:

.demoModalShadow {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%!important;
    height: 100%!important;
    justify-content: center;
    align-items: center;
    background: rgba(204, 204, 204, 0.4);
    z-index: 99999;
    display: none;
}

Теперь у наше модальное окно полностью стилизовано. Осталось добавить интерактивности.

Добавление интерактивности

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

Предположим, мы хотим запускать поп-ап при нажатии на кнопку. Создадим эту кнопку, присвоив ей идентификатор:

<button id='demoModalStart' class='demoModalStart'>Подписаться!</button>
.demoModalStart {
    cursor: pointer;
    display: inline-block;
    text-align: center;
    word-break: break-word;
    box-sizing: border-box;
    transition: all .3s;
    background: #00c1c5;
    color: #fff;
    border-radius: 12px;
    padding: 10px 24px;
    font-size: 1.125em;
    border: none;
}

При нажатии на эту кнопку мы изменим значение свойства display с none на flex у модального окна, чем отобразим окно. Закрытие поп-апа будет осуществляться нажатием на кнопку «Закрыть» самой формы. Соответственно, процесс подписки (его имитация) будет запускаться при нажатии на кнопку формы «Подписаться». После подписки мы отобразим сообщение с благодарностью на самой форме. Эту интерактивность добавим с помощью JavaScript.

Таким образом, выведем финальный код работающего модального окна.

HTML:

<div id="demoModalShadow" class="demoModalShadow">
    <form id="demoModal" class="demoModal">
        <h2>Подписка на рассылку</h2>
        <div id="demoModalInfo" class="demoModal__info">
            <label for="email">Введите ваш email для подписки на нашу рассылку:</label>
            <input type="email" name="email" id="email" placeholder="your@email.com" required>
        </div>
        <div class="demoModal__actions">
            <input type="submit" id="demoModalSubscribe" class="demoModal__button active" value="Подписаться">
            <input type="button" id="demoModalClose" class="demoModal__button close" value="Закрыть">
        </div>
    </form>
</div>

<button id='demoModalStart' class='demoModalStart'>Подписаться!</button>

CSS:

/* Content */
.demoModal {
    padding: 20px;
    width: 320px;
    background-color: #393939;
    box-shadow: 0 0 10px 0 #fff;
    border-radius: 10px;
    z-index: 1000;
    text-align: center;
}

.demoModal h2 {
    color: #00c1c5;
    font-size: 1.3em;
}

.demoModal label {
    color: #fff;
    font-size: 0.9em;
    margin-bottom: 0.1em!important;
}

.demoModal__info {
    margin-top: 0.7em;
    color: #fff;
}

.demoModal input[type='email'] {
    width: 100%;
    font-size: 1.2em;
    box-sizing: border-box;
    border: 1px solid #ccc;
    border-radius: 5px;
    padding: 10px;
    margin-top: 0.6em;
}

.demoModal__actions {
    margin-top: 0.8em;
}

.demoModal__button {
    padding: 5px 10px;
    color: #fff;
    background-color: transparent;
    border: 2px solid #fff;
    cursor: pointer;
    font-size: 16px;
    border-radius: 5px;
    margin: 10px;
    transition: all .3s;
}

.demoModal__button.active {
    background-color: #00c1c5;
}

.demoModal__button.active:hover {
    color: #00c1c5;
    background-color: #fff;
}

.demoModal__button.close {
    color: #393939;
    background-color: #ccc;
}

.demoModal__button.close:hover {
    background-color: #a9a9a9;
}

/* Shadow */
.demoModalShadow {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%!important;
    /*max-width: 100%!important;*/
    height: 100%!important;
    /*max-height: 100%!important;*/
    justify-content: center;
    align-items: center;
    background: rgba(204, 204, 204, 0.4);
    z-index: 99999;
    display: none;
}

/* Start button */
.demoModalStart {
    cursor: pointer;
    display: inline-block;
    text-align: center;
    word-break: break-word;
    box-sizing: border-box;
    transition: all .3s;
    background: #00c1c5;
    color: #fff;
    border-radius: 12px;
    padding: 10px 24px;
    font-size: 1.125em;
    border: none;
}

JavaScript:

// Открытие модального окна
document.querySelector('#demoModalStart').addEventListener('click', function () {
    document.querySelector('#demoModalShadow').style.display = 'flex';
});

// Закрытие модального окна
document.querySelector('#demoModalClose').addEventListener('click', function () {
    document.querySelector('#demoModalShadow').style.display = 'none';
});

// Обработка подписки (здесь просто выводим сообщение с благодарностью за подписку)
document.querySelector('#demoModal').addEventListener('submit', function (e) {
    // Отменяем поведение формы по умолчанию (чтобы не закрывалась)
    e.preventDefault();

    document.querySelector('#demoModalInfo').innerHTML = '<p>Благодарим за подписку!</p>';
    document.querySelector('#demoModalSubscribe').style.display = 'none';
});

Запустить готовое модальное окно вы можете, нажав на кнопку ниже:

Подписка на рассылку

Оцените статью
DevReflex
Добавить комментарий