Как создать модальное окно на jQuery

Модальное окно на jQuery открывается по ссылке, затемняет страницу и закрывается кнопкой, кликом по подложке или клавишей Esc. Вы соберете пример из HTML, CSS и JavaScript, добавите управление фокусом и автоматический показ раз в 7 дней.

Как создать простое всплывающее окно HTML

Разделите пример на 4 файла: index.html, popup.css, popup.js и локальную копию jQuery. Разметка задает содержимое, CSS оформляет окно, JavaScript управляет показом, закрытием и cookie.

Добавьте разметку окна и подложки

Вставьте ссылку в содержимое страницы, а окно и подложку разместите рядом с ней. Обертка #page-content позволит временно заблокировать фон через атрибут inert.

<main id="page-content">
    <a href="#modal" name="modal">Открыть модальное окно</a>
</main>

<div id="modal-overlay" class="modalwindow-overlay" hidden></div>

<div id="modal" class="modalwindow" role="dialog"
     aria-modal="true" aria-labelledby="modal-title"
     tabindex="-1" hidden>
    <h2 id="modal-title">Простое модальное окно на jQuery</h2>
    <button type="button" class="modalwindow-close"
            aria-label="Закрыть">×</button>
    <div class="modalwindow-content">
        <p>Здесь можно разместить сообщение для посетителя.</p>
        <a href="/">На главную</a>
    </div>
</div>

Ссылка указывает на #modal, а идентификатор окна равен modal. Обработчик найдет нужный элемент по этому адресу.

Атрибут aria-labelledby связывает диалог с заголовком. Кнопка получает доступное имя через aria-label, а tabindex="-1" позволяет перевести фокус на окно.

Оформите окно в popup.css

Сохраните стили в файле popup.css рядом с index.html. Центрирование через transform убирает расчеты координат из JavaScript и сохраняет окно по центру при изменении размера экрана.

.modalwindow-overlay {
    position: fixed;
    inset: 0;
    z-index: 9998;
    background: rgb(0 0 0 / 60%);
}

.modalwindow {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 9999;
    box-sizing: border-box;
    width: 500px;
    max-width: 90%;
    max-height: 90vh;
    overflow-y: auto;
    background: #fff;
    color: #222;
    font-family: Arial, sans-serif;
    box-shadow: 0 8px 24px rgb(0 0 0 / 35%);
}

.modalwindow h2 {
    margin: 0;
    padding: 20px 60px 20px 20px;
    background: #e64a19;
    color: #fff;
    font-size: 24px;
}

.modalwindow-content {
    padding: 20px;
    font-size: 18px;
    line-height: 1.5;
}

.modalwindow-close {
    position: absolute;
    top: 10px;
    right: 10px;
    width: 40px;
    height: 40px;
    border: 0;
    background: #fff;
    color: #222;
    font-size: 28px;
    cursor: pointer;
}

.modalwindow :focus-visible {
    outline: 3px solid #1459b5;
    outline-offset: 2px;
}

Селекторы начинаются с .modalwindow, поэтому стили не меняют другие заголовки и кнопки сайта. Ограничение высоты добавляет прокрутку длинному содержимому, а max-width оставляет поля на узком экране.

Подготовьте jQuery и файлы примера

Откройте защищенный адрес https://code.jquery.com/ и выберите сборку jQuery: uncompressed удобна для отладки, а minified занимает меньше места. Сохраните файл рядом с index.html под именем jquery.js. Синтаксис методов библиотеки описан в официальной документации jQuery.

Создайте пустой файл popup.js. Полный код для него приведен в разделе о cookie. В итоговой папке должны лежать 4 файла.

Подключите файлы в правильном порядке

Подключите CSS внутри <head>, а скрипты поставьте перед закрывающим тегом </body>. jQuery должна загрузиться раньше собственного кода.

<link rel="stylesheet" href="popup.css">

<script src="jquery.js"></script>
<script src="popup.js"></script>

Обертка $(function () { ... }) в popup.js дождется готовности DOM. Поэтому обработчик найдет ссылку, окно и подложку после загрузки разметки.

Откройте окно по ссылке

Обработчик извлекает адрес ссылки и передает его в $(). Внешний вызов превращает строку #modal в объект jQuery.

$('a[name="modal"]').on('click', function (event) {
    event.preventDefault();
    var id = $($(this).attr('href'));
    openModal(id, this);
});

Вызов attr('href') возвращает строку, у которой нет метода css(). Выражение $($(this).attr('href')) превращает адрес в объект jQuery и передает его функции открытия.

Настройка cookies

Cookie popup=hide хранит отметку о показе 7 дней. Скрипт читает ее после загрузки DOM и открывает окно автоматически, если отметки нет.

Ручное открытие по ссылке работает при любой cookie. Кнопка, подложка и клавиша Esc вызывают одну функцию closeModal().

Добавьте полный файл popup.js

Скопируйте код целиком в popup.js. Значение autoShow = true включает автоматический запуск, а false оставляет только открытие по ссылке.

function createCookie(name, value, days) {
    var expires = '';

    if (typeof days === 'number') {
        var date = new Date();
        date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
        expires = '; expires=' + date.toUTCString();
    }

    document.cookie = encodeURIComponent(name) + '=' +
        encodeURIComponent(value) + expires + '; path=/; SameSite=Lax';
}

function readCookie(name) {
    var prefix = encodeURIComponent(name) + '=';
    var cookies = document.cookie.split(';');

    for (var i = 0; i < cookies.length; i++) {
        var cookie = cookies[i].trim();
        if (cookie.indexOf(prefix) === 0) {
            return decodeURIComponent(cookie.substring(prefix.length));
        }
    }

    return null;
}

function eraseCookie(name) {
    createCookie(name, '', -1);
}

$(function () {
    var autoShow = true;
    var $modal = $('#modal');
    var $overlay = $('#modal-overlay');
    var page = document.getElementById('page-content');
    var returnFocus = null;
    var previousOverflow = '';
    var previousInert = false;
    var isOpen = false;

    function focusableElements() {
        return $modal.find(
            'a[href], button, input, select, textarea, [tabindex]'
        ).filter(function () {
            return this.tabIndex >= 0 &&
                !this.disabled && $(this).is(':visible') &&
                !this.closest('[inert]');
        });
    }

    function openModal($target, trigger) {
        if (isOpen || $target[0] !== $modal[0]) return;

        returnFocus = trigger || document.activeElement;
        previousOverflow = document.documentElement.style.overflow;
        previousInert = page.inert;
        isOpen = true;

        $overlay.prop('hidden', false);
        $modal.prop('hidden', false);
        document.documentElement.style.overflow = 'hidden';
        page.inert = true;
        $modal.find('.modalwindow-close')[0].focus();
        createCookie('popup', 'hide', 7);
    }

    function closeModal() {
        if (!isOpen) return;

        isOpen = false;
        page.inert = previousInert;
        $modal.prop('hidden', true);
        $overlay.prop('hidden', true);
        document.documentElement.style.overflow = previousOverflow;

        if (returnFocus && returnFocus.isConnected &&
            returnFocus !== document.body) {
            returnFocus.focus();
        } else {
            var fallback = document.querySelector('a[name="modal"]');
            if (fallback) fallback.focus();
        }
    }

    $('a[name="modal"]').on('click', function (event) {
        event.preventDefault();
        var id = $($(this).attr('href'));
        openModal(id, this);
    });

    $modal.find('.modalwindow-close').on('click', closeModal);
    $overlay.on('click', closeModal);

    $(document).on('keydown', function (event) {
        if (!isOpen) return;

        if (event.key === 'Escape') {
            event.preventDefault();
            closeModal();
            return;
        }

        if (event.key !== 'Tab') return;

        var $items = focusableElements();
        var first = $items[0];
        var last = $items[$items.length - 1];
        var active = document.activeElement;

        if (!first) {
            event.preventDefault();
            $modal[0].focus();
        } else if (event.shiftKey &&
                   (active === first || active === $modal[0])) {
            event.preventDefault();
            last.focus();
        } else if (!event.shiftKey &&
                   (active === last || active === $modal[0])) {
            event.preventDefault();
            first.focus();
        }
    });

    $(document).on('focusin', function (event) {
        if (isOpen && !$modal[0].contains(event.target)) {
            $modal[0].focus();
        }
    });

    if (autoShow && readCookie('popup') !== 'hide') {
        openModal($modal);
    }
});

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

Значение 7 передается числом, а toUTCString() формирует дату окончания cookie. Чтобы снова увидеть автоматическое окно, выполните eraseCookie('popup') в консоли браузера и обновите страницу.

Подготовьте локальный сервер и проверьте окно

Откройте терминал в папке с примером командой cd "путь-к-папке". Для запуска нужен установленный Python с доступной командой python.

Если Python не установлен, установите его по официальной инструкции Python, затем повторите проверку версии.

Выполните python --version, затем запустите локальный сервер. После запуска терминал сообщит, что он принимает подключения.

python -m http.server 8000

Откройте в браузере адрес http://127.0.0.1:8000/index.html. Если команда python не найдена, проверьте установку Python и имя команды в терминале.

  1. Установите autoShow = false и обновите страницу. Автоматическое окно не появится.
  2. Нажмите ссылку открытия. Появятся окно и затемняющая подложка.
  3. Нажмите кнопку «Закрыть». Оба элемента исчезнут, а фокус вернется на ссылку.
  4. Откройте окно снова и нажмите на подложку. Диалог закроется.
  5. Откройте окно еще раз и нажмите Esc. Результат совпадет с закрытием кнопкой.
  6. Откройте окно повторно, нажмите Tab и Shift+Tab. Фокус останется внутри диалога.
  7. Верните autoShow = true, выполните в консоли eraseCookie('popup') и обновите страницу.
  8. Закройте диалог и обновите страницу повторно. Cookie подавит автоматический показ.

Если браузер сообщает $ is not defined, проверьте имя jquery.js и порядок подключения двух скриптов. Чтобы вернуть ручной режим, установите autoShow = false.

Как сделать модальное окно без jQuery

Нативный элемент <dialog> открывается модально через showModal(). Браузер создает подложку и блокирует взаимодействие с остальной страницей.

Этот вариант подходит для нового проекта, если вам не нужны jQuery и собственная логика cookie.

<button id="open-dialog" type="button">Открыть окно</button>

<dialog id="native-modal" aria-labelledby="native-title">
    <h2 id="native-title">Сообщение</h2>
    <p>Это модальное окно без jQuery.</p>
    <form method="dialog">
        <button autofocus>Закрыть</button>
    </form>
</dialog>

<script>
const dialog = document.getElementById('native-modal');
document.getElementById('open-dialog').addEventListener('click', () => {
    dialog.showModal();
});
</script>

Готовая HTML-страница для подключения окна

Сохраните код как index.html в папке с popup.css, popup.js и jquery.js. Скрипты подключены после разметки, поэтому обработчик получает готовые элементы.

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Модальное окно на jQuery</title>
    <link rel="stylesheet" href="popup.css">
</head>
<body>
    <main id="page-content">
        <a href="#modal" name="modal">Открыть модальное окно</a>
    </main>

    <div id="modal-overlay" class="modalwindow-overlay" hidden></div>

    <div id="modal" class="modalwindow" role="dialog"
         aria-modal="true" aria-labelledby="modal-title"
         tabindex="-1" hidden>
        <h2 id="modal-title">Простое модальное окно на jQuery</h2>
        <button type="button" class="modalwindow-close"
                aria-label="Закрыть">×</button>
        <div class="modalwindow-content">
            <p>Здесь можно разместить сообщение для посетителя.</p>
            <a href="/">На главную</a>
        </div>
    </div>

    <script src="jquery.js"></script>
    <script src="popup.js"></script>
</body>
</html>

Сохраните 4 файла в одной папке и откройте страницу через локальный сервер. Сначала проверьте ручное открытие, кнопку, подложку и клавишу Esc, затем включите автоматический показ через autoShow = true.

Комментарии

Оставьте свой комментарий
Пока никто не оставил комментариев