Роздуми про стилізації модальних вікон

22

Від автора: модальний – невеликий блок, вистрибує з яким-небудь важливим повідомленням. До якої складності можна віднести такі конструкції? На мій погляд, це середня складність. Для правильної роботи таких вікон треба врахувати парочку речей і трюків. Давайте порахуємо їх.

Де в DOM знаходяться модальні вікна?

Я зазвичай розміщую HTML код модальних вікон перед закриваючим тегом body.

Роблю я це в основному з причин стилізації. Позиціонувати модальні вікна стосовно тега body, який покриває всю сторінку, набагато легше, на відміну від незрозумілого набору батьківських елементів, у кожного з яких може бути свій контекст позиціонування.

Як це впливає на скрін рідери? Я не експерт по доступності, але чув, що модальні вікна досить складна штука. Роб Додсон:

Хто намагався хоч раз зробити модальні вікна доступним, знають, що, незважаючи на свій привабливий вигляд, модальні вікна – це як битва з босом в кінці гри під назвою веб-доступність. Вони вас проковтнуть і виплюнуть останки. Наприклад, правильне модальне вікно повинно володіти наступними особливостями:

фокус клавіатури повинен переміститися на модальне вікно, а при його закритті повинен повернутися до попереднього activeElement;

фокус клавіатури повинен бути заблокований на модальному вікні, щоб користувач випадково за допомогою клавіші Tab не вийшов за межі вікна;

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

Роб створив супер доступне демо з модальним вікном. Також я бачив недавній приклад Ноя Блона і Ніколаса Хоффмана. Також можна подивитися ARIA Live Regions. Якщо ви обробляєте фокус вручну, нижня частина сторінки найбільш підходящий варіант розміщення модального вікна.

Центрування

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

.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

Відмінно підходить для модальних вікон, які зазвичай розташовані точно по центру екрану і можуть бути різної ширини. Висота вікна змінюється в залежності від контенту.

Роздуми про стилізації модальних вікон

Якщо ви точно знаєте ширину і висоту вікна, можна скористатися іншими методами. Я взяв цей метод, тому що є шанс, що текст буде злегка розмитим і трансформується. Якщо ви не розумієте, про що я кажу, пошукайте інші методи у посібнику центрування (наприклад, негативні магдіп’и).

Фіксоване розташування?

Зверніть увагу, ми використовували position: fixed;. Суть в тому, що користувач може прокрутити сторінку, викликати модальне вікно, і вона буде точно так само центроване, як якщо б він відразу його викликав.

На мій погляд, фіксоване позиціонування зараз безпечно використовувати, навіть на мобільних пристроях. Однак якщо ви точно знаєте, що у вас досить велика аудиторія з дуже старими мобільними пристроями, з фіксованим розташуванням можуть виникнути проблеми. У такому разі візьміть position: absolute і примусово прокрутіть сторінку вгору. Або що-небудь ще, не знаю, тестуйте інші способи.

Робота з шириною

На великих екранах звичайне модальний не просто центроване, воно також має обмежену ширину (як на скріншоті вище).

.modal {
/* вже пройдені стилі */
width: 600px;
}

Проблемне місце. На великих екранах у нас все добре, але є безліч екранів, які в ширину навіть не 600px.

Роздуми про стилізації модальних вікон

Легко виправити за допомогою max-width:

.modal {
/* вже пройдені стилі */
width: 600px;
max-width: 100%;
}

Роздуми про стилізації модальних вікон

Робота з висотою

З висотою проблем ще більше. Контент адже може змінюватися! Метод центрування за допомогою трансформацій так і норовить відрізати верхівку вікна, а смуги прокрутки у нас немає:

Роздуми про стилізації модальних вікон

Нас знову врятує максимальне значення:

.modal {
/* вже пройдені стилі */
height: 400px;
max-height: 100%;
}

Роздуми про стилізації модальних вікон

Робота з перекриттям

Ми намагаємося вирішити питання з висотою модального вікна. Тепер нам потрібно врахувати ще й перекриття. Заманливо було б використовувати властивість overflow прямо на елементі .modal, але тут виникають дві проблеми:

у нас можуть бути елементи, які не потрібно прокручувати;

перекриття відріже тінь box-shadow, яка нам може знадобитися.

Я би запропонував ввести внутрішній контейнер:

Щоб область .modal-guts прокручувалася, їй необхідно вказати висоту. Тут багато способів. Один із способів – встановити внутрішній контейнер так, щоб він перекривав всі модальне вікно, а потім додати перекриття:

.modal-guts {
/* вже пройдені стилі */
/* перекриваємо модальне вікно */
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* додаємо відступів, якщо потрібно */
padding: 20px 50px 20px 20px;
/* додаємо смугу прокрутки */
overflow: auto;
}

Роздуми про стилізації модальних вікон

Кнопки

Модальні вікна повинні примушувати користувача до якої-небудь дії, поки не сталося щось ще. Якщо вам не потрібно примушувати користувача до дії, розгляньте інший UI елемент. З модального вікна повинен бути вихід. Для модального вікна характерні різні кнопки і перемикачі (наприклад, «Видалити»/«Скасувати»), а також кнопка закриття. Додамо в наше вікно кнопку закриття.

Було б розумно, розташувати кнопку закриття так, щоб вона постійно була на виду. Щоб у користувача не виникло ситуації, коли він не знає, як закрити вікно. Ось для цього ми і залишили область без прокручування.

Роздуми про стилізації модальних вікон

Стилі додасте самі Роздуми про стилізації модальних вікон

Робота з накладенням

Модальні вікна часто з’являються на повноекранному перекрывающем тлі. Корисна річ з ряду причин:

перекриває шар може затемнювати сторінку, посилюючи тим самим основну мету модального вікна;

такий шар може врятувати від взаємодії з тим, що знаходиться поза модального вікна;

перекриває шар можна використовувати в якості великої кнопки закриття, скасування.

Типовий код:

.modal {
/* вже пройдені стилі */
z-index: 1010;
}
.modal-overlay {
/* рекомендація:
Не зациклюйтеся на значенні «1000», у вас
повинна бути задокументована система для властивості z-index,
якої необхідно дотримуватися. Це значення має бути
досить великим у вашій системі.
*/
z-index: 1000;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

Закриття по класу, а не відкриття

Вкрай заманливо за замовчуванням заховати клас .modal за допомогою властивості display: none;. Потім з відкриття вікна додавати клас .modal.open { display: block; }.

Бачите властивість display: block;? Ось тут і проблема. Властивість display: none; дуже корисно, так як воно ховає вікно не тільки візуально, але і від допоміжних технологій для людей з обмеженими можливостями. Легше застосовувати властивість поверх існуючого значення властивості display, а не переписувати значення навмання. Модальне вікно .modal може використовувати display: flex;, display: grid; або що-небудь інше. Різні модальні вікна можуть використовувати будь-які значення і не боятися скинути його на display: block;.

.modal {
/* наприклад… */
display: flex;
}
.modal.closed {
display: none;
}

Перемикач відкриття і закриття

Самий базовий спосіб для відкриття і закриття вікна:

var modal = document.querySelector(«#modal»);
var modalOverlay = document.querySelector(«#modal-overlay»);
var closeButton = document.querySelector(«#close-button»);
var openButton = document.querySelector(«#open-button»);
closeButton.addEventListener. («click», function() {
modal.classList.toggle(«closed»);
modalOverlay.classList.toggle(«closed»);
});
openButton.addEventListener. («click», function() {
modal.classList.toggle(«closed»);
modalOverlay.classList.toggle(«closed»);
});

Вікно поки що ще недоступне для скрін рідерів. Згадайте, про що ми говорили вище. За посиланням ви знайдете демо, в якому фокус переходить на модальний, блокується на ньому і повертається на той елемент, з якого прийшов.