Как создать модальное окно От Редакция techrocks.ru / 19.01.2025 Перевод статьи “How to Build an Accessible Modal – with Example Code”. Мы часто используем модальные или всплывающие окна для отображения важной информации или побуждения пользователей к действию. В отличие от обычных всплывающих окон, которые могут открываться в новых окнах или вкладках, эти диалоги удерживают пользователя на одной странице, накладываясь на существующий контент. Благодаря этому пользователи не отвлекаются от выполнения поставленной задачи. Модальные окна довольно часто используются на сайтах, порой без них не обойтись. Но если они реализованы неправильно, то могут серьезно испортить пользовательский опыт. Такие элементы дизайна должны быть доступными, чтобы ими моли пользоваться все, в том числе люди, применяющие вспомогательные технологии. В этой статье мы создадим модальное окно с учетом рекомендаций по доступности. Необходимые условия Чтобы следовать этому руководству, у вас должны быть: Базовые знания HTML. Нужно понимать, как работают элементы и атрибуты HTML. Базовые знания JavaScript. Знакомство с основными концепциями JavaScript, такими как функции, обработка событий и манипуляции с DOM, будет полезным. Понимание ARIA. Хотя в этом руководстве объясняются роли и атрибуты ARIA, базовое понимание концепций доступности будет не лишним. Когда следует использовать модальные окна? Эффективное использование модальных окон требует внимательного отношения к пользовательскому опыту. Вот несколько рекомендаций, которые помогут вам решить, стоит ли использовать модальные окна: Модальные окна следует использовать, когда пользователю необходимо принять важное решение, например, подтвердить потенциально разрушительное действие (скажем, удаление элемента) или согласиться с условиями и правилами. Вы можете использовать модальное окно, когда задача требует полного внимания пользователя и не зависит от информации с остальной части страницы (например, заполнение формы или завершение процесса оплаты). Модальное окно можно использовать для отображения временной или преходящей информации, которая не должна постоянно отображаться на странице (предупреждения, уведомления или короткие сообщения). Не стоит использовать модальные окна для задач, требующих длительного взаимодействия или ввода, например, для длинных форм или сложных рабочих процессов. Пользователю может быть неудобно работать в модальном окне из-за ограниченного пространства и навигационных ограничений. Не стоит использовать модальные окна для действий, которые пользователь должен выполнять часто. Постоянно всплывающие окна могут раздражать. Не следует использовать модальные окна, если они прерывают естественный ход работы пользователя на сайте, особенно если содержимое или действие в окне не является срочным или важным. Рекомендации по доступности модальных окон Вот несколько советов, которые помогут вам создать полезные и доступные модальные окна: Предусмотрите описательный атрибут aria-labelledby, указывающий на заголовок модального окна. Если заголовка нет, используйте aria-label для создания короткой описательной метки. В модальном окне обязательно должна быть видимая и легкодоступная кнопка закрытия (обычно ее располагают в правом верхнем углу). Четко обозначьте эту кнопку, например, текстом «Закрыть» или значком с aria-label="Закрыть". При открытии модального окна фокус клавиатуры должен перемещаться на первый интерактивный элемент внутри этого окна (обычно это кнопка закрытия). После закрытия модального окна фокус должен возвращаться к элементу, который вызвал модальное окно. Сохраняйте фокус клавиатуры внутри модального окна, пока оно открыто. Предоставляйте пользователям возможность закрывать модальные окна нажатием клавиши Escape. А теперь давайте создадим модальное окно, следуя этим рекомендациям. Я предпочитаю использовать правильные HTML-теги для создания компонентов, и в данном случае я буду использовать тег dialog. Как создать модальное окно с помощью тега dialog Тег dialog появился в HTML5. Он используется для создания диалоговых окон, таких как всплывающие окна, оповещения и модальные окна. Этот тег предлагает встроенные методы и атрибуты, облегчающие управление поведением окна без использования большого количества JavaScript-кода. Встроенные методы JavaScript — это show(), showModal() и close(). show() и showModal() С помощью метода show() можно создать неблокирующее диалоговое окно. Такое окно отображается поверх текущего содержимого, но пользователи могут взаимодействовать с другими частями веб-страницы (нажимать кнопки, ссылки и т. д.), пока окно открыто. Это полезно в ситуациях, когда диалоговое окно предоставляет информацию, которая не требует немедленного внимания пользователя. Вот пример: <!-- Previous content here -->
<dialog id="dialog-box">
<!-- More content here -->
</dialog>

<script>
    const dialog = document.getElementById('dialog-box');
    dialog.show();
</script> Результат: Метод showModal() открывает диалоговое окно в модальном режиме. Это означает, что окно принимает фокус, а взаимодействие с остальной частью веб-страницы блокируется до тех пор, пока окно не будет закрыто. Пользователь не может кликать или как-то иначе взаимодействовать с любой другой частью страницы. В зависимости от браузера за диалоговым окном может появляться полупрозрачный фон, визуально указывающий на то, что с остальной частью страницы невозможно взаимодействовать. Когда диалоговое окно открывается с помощью showModal(), фокус автоматически удерживается внутри окна. Пользователь может переходить к различным элементам внутри диалогового окна с помощью клавиши табуляции, и фокус будет циклически перемещаться по содержимому окна до тех пор, пока оно не будет закрыто. Вот пример: <dialog id="dialog-box">
<!-- More content here -->
</dialog>

<script>
    const dialog = document.getElementById('dialog-box');
    dialog.showModal();
</script> Результат: Элемент <dialog> имеет стили по умолчанию, но его можно настроить с помощью CSS в соответствии с вашим дизайном. Вы можете изменить стиль диалогового окна, добавить анимацию или изменить фон. Фон можно стилизовать с помощью селектора ::backdrop. Например: dialog::backdrop {
    background: rgba(0, 0, 0, 0.7);
} Элемент <dialog> также оснащен некоторыми встроенными функциями доступности, такими как управление фокусом, задний фон, автоматическое объявление при открытии и закрытие диалогового окна нажатием клавиши ESC. Вы можете добавить атрибут autofocus к первому интерактивному элементу в модальном окне, например, к первому вводимому элементу формы или кнопке закрытия. В качестве альтернативы можно полагаться на встроенную функцию управления фокусом в элементе <dialog>. Избегайте использования tabindex для элемента <dialog>, поскольку он не является интерактивным элементом, таким как кнопка или ссылка. Элемент <dialog> служит контейнером для интерактивного содержимого, он не предназначен для получения фокуса напрямую. Элемент <dialog> обеспечивает нативный способ создания модальных окон. Если вы создаете кастомизированное модальное окно, убедитесь, что его функции доступности соответствуют возможностям нативного элемента <dialog>. Собираем все вместе: <style>
    dialog::backdrop {
        background: rgba(0, 0, 0, 0.7);
    }
</style>
<body>
    <button id="open-dialog">Open Dialog</button>
    <dialog id="dialog-box">
        <h2>Modal title</h2>
        <div>
          <!-- More content here -->
          <button id="close-dialog" autofocus>Close</button>
        </div>
    </dialog>

<script>
    const dialog = document.getElementById("dialog-box");
    const openButton = document.getElementById("open-dialog");
    const closeButton = document.getElementById("close-dialog");

    openButton.addEventListener("click", () => {
      dialog.showModal();
    });
    closeButton.addEventListener("click", () => {
      dialog.close();
    });
</script>
</body> Вы заметили, что я не использовала атрибут aria-label в диалоговом окне, как было рекомендовано. Это потому, что хорошо структурированный элемент диалогового окна не обязательно нуждается в таком атрибуте. В данном случае в элементе диалогового окна есть видимая метка (элемент h2). Если видимых меток нет, то их нужно добавить. Как в этом примере: <dialog id="confimation-dialog" aria-label="Confirmation Dialog">
    <p>Are you sure you want to proceed?</p>
    <button id="close-dialog" autofocus>Close</button>
</dialog> Что такое атрибут inert? Когда модальное окно открыто, устройство чтения с экрана (скринридер) может переходить к содержимому вне модального окна. Обычно нужно, чтобы фокус пользователя был ограничен самим модальным окном или чтобы пользователь не мог случайно нажать на элементы вне модального окна, чтобы избежать путаницы и ошибок. Для такого ограничения вам понадобится атрибут inert. Атрибут inert делает элемент и всех его потомков неинтерактивными и недоступными для вспомогательных технологий. Когда модальное окно открыто, использование атрибута inert для остального содержимого страницы обеспечит доступ только к содержимому модального окна, что сделает диалог более понятным. Как использовать атрибут inert Когда модальное окно открыто, вы можете применить атрибут inert к остальному содержимому страницы (обычно к элементу <main>). Когда модальное окно закрывается, вы удаляете атрибут inert. Вот пример, показывающий, как использовать inert в модальном диалоге: <body>
    <header>Site Header</header>
    <main id="main-content">
        <button id="open-dialog">Open modal</button>
        <p>This is the main content of the page.</p>
        <!-- More content here -->

    </main>
    <!-- Move the dialog outside the main element -->
    <dialog id="dialog">
        <h2>Modal Title</h2>
        <p>This is the content inside the modal.</p>
        <button id="close-dialog" autofocus>Close</button>
    </dialog>

    <script>
        const dialog = document.getElementById('dialog');
        const mainContent = document.getElementById('main-content');
        const openButton = document.getElementById('open-dialog');
        const closeButton = document.getElementById('close-dialog');

        openButton.addEventListener("click", () => {
           mainContent.setAttribute('inert', '');
          dialog.showModal();
        });

        closeButton.addEventListener("click", () => {
           dialog.close();
        });

        // the dialog elemnt has a close event, which is called when a user calls the close() method or presses the esc key
        dialog.addEventListener("close", (event) => {
           mainContent.removeAttribute("inert");
        });
    </script>
</body> Как анимировать состояния открытия и закрытия Когда модальное окно появляется (состояние открытия) или исчезает (состояние закрытия), резкость перехода может вызвать раздражение у пользователей. Анимация этих состояний может создать более плавный пользовательский опыт. Зачем анимировать состояния открытия и закрытия? Анимация состояний открытия и закрытия модального окна может: Улучшить пользовательский опыт. Плавная анимация может сделать переход менее резким и более интересным. Привлечь внимание. Легкая анимация поможет направить внимание пользователя на содержимое модального окна при его появлении. Поддержать единообразие. Последовательная анимация во всем пользовательском интерфейсе может создать ощущение целостности и профессионализма. По умолчанию <dialog> настроен на display:none, когда он закрыт, и display:block, когда открыт. Переход от none к block в CSS невозможен, но вы можете комбинировать свойства display с transform или opacity. Свойство transform можно использовать для масштабирования или перемещения модального окна, а opacity управляет его прозрачностью. Вот пример того, как можно анимировать модальное окно: dialog {
  animation: zoom-out 0.5s ease-out;
}

/* an open attribute is added to the dialog when it is open  */
dialog[open] {
    animation: zoom-in 0.5s ease-out;
}

/* The display property in the keyframes is critical 
because it toggles the modal’s visibility on and off.  */
@keyframes zoom-in {
    0% {
      opacity: 0;
      transform: scale(0.1);
      display:  none;
    }
    100% {
      opacity: 1;
      transform: scale(1);
      display: block;
    }
}

@keyframes zoom-out {
    0% {
      opacity: 1;
      transform: scale(1);
      display: block;
    }
    100% {
      opacity: 0;
      transform: scale(0);
      display: none;
    }
} Конечный результат: See the Pen Modal Sample by Elizabeth (@leezee) on CodePen. Заключение Элемент <dialog> — это основной способ создания модальных окон. Он предоставляет встроенные функции, доступные как для пользователей клавиатуры, так и для пользователей скринридеров. Элемент <dialog> бывает модальным и немодальным. Вы можете создать немодальный диалог с помощью метода show(), а с помощью метода showModal() — модальный. Если вы не используете нативный элемент dialog, следите за тем, чтобы ваше модальное окно соответствовало окнам, созданным с помощью элемента dialog, с точки зрения доступности, чтобы обеспечить единый опыт для всех пользователей. Также не забывайте автоматически помещать в фокус элемент, который должен стать интеркативным с самого начала. Элемент dialog может делать это по умолчанию. Наконец, вы можете использовать атрибут inert для других элементов, чтобы предотвратить доступ к ним при открытом модальном окне. 7 уроков дизайна для разработчиков 1 комментарий / Новости, Обучение / От andrey_av Не документируйте код. Кодируйте документацию 1 комментарий / Новости, Обучение / От andrey_av
==============
Создание доступных модальных окон с использованием HTML и JavaScript. Важно учитывать, что модальные окна, в отличие от обычных, удерживают пользователя на одной странице, не открываясь в новых вкладках. Для обеспечения доступности необходимо использовать тег dialog, который предоставляет встроенные методы и атрибуты для управления поведением окна. Важные аспекты включают: предоставление описательного атрибута aria-labelledby для заголовка, наличие видимой и доступной кнопки закрытия, фокус клавиатуры, возможность закрытия с помощью клавиши Escape и, при необходимости, использование атрибута inert для ограничения интерактивности других элементов страницы. Анимация состояний открытия и закрытия модального окна улучшает пользовательский опыт.