Comments 19
Прикольная штука, и не новая уже, а я вот только узнал. Спасибо!
Спасибо. Было интересно
Интересно, спасибо. Осталось еще разобраться мне, как добавить обработку нативной операции Бек по истории в Андроид, так чтобы закрывался попап вместо хождения по истории и перегрузки страницы.. Буду рад советам
Предположу, что можно связать попап с якорем или другим изменением урла, и тогда "хождение по истории" будет его закрывать (но это не точно).
На событие открытия модального окна добавляете элемент в историю:
window.history.pushState(null, null, document.location);
show = true;
Отслеживаете изменение истории (нажатие на кнопку "назад"):
addEventListener('popstate', function(e) {
if (show) {
dialogElement.close();
history.back();
show = false;
}
}
Также на событие закрытие модального окна убираете событие в истории, чтобы на кнопку "назад" не нужно было потом кликать два раза:
history.back();
show = false;
Как-то так %)
Какие примеры конкретных сценариев или задач вы видите, где HTML-элемент может быть особенно полезен в сравнении с традиционными подходами, такими как использование самописных решений или встроенных методов alert(), prompt() и confirm()?
Это могут любые задачи, вплоть до использования <dialog>
в UI-библиотеках для фреймворков на боевых проектах. Лично я в своих приложениях уже давно переписал все модалки на нативный элемент и радуюсь, что в стандарте учтены основные проблемы реализации, которые раньше нужно было предусматривать самому, или же пользоваться внешними решениями типа a11y-dialog, хотя мне может не требоваться вся их функциональность.
Спасибо. А Вам не кажется, что с полифилом получается сложновато, а JS реализации универсальны и не требуют ни переписывания, ни полифила.
Я считаю, что JS-реализации по умолчанию хуже полноценного нативного стандарта, потому что разработаны и поддерживаются не производителями конечных технологий — браузеров, а такими же разработчиками, как и мы с вами. Как следствие, эти реализации могут перестать поддерживаться в будущем. Кроме того, они могут использовать различные хаки и нестандартизированные приёмы для того, чтобы эмулировать поведение, которое работает в нативных реализациях. К примеру, в них может эмулироваться функциональность глобального атрибута inert
, блокирующего действия над остальной страницей под модальным окном или же поведение фокуса, которое давно стандартизированно в нативной реализации. В конце концов, такие реализации могут быть слишком тяжеловесными в рамках конкретного проекта, да и в целом это лишняя внешняя зависимость. Впрочем, некоторые проблемы в нативной реализации до сих пор остаются, подробнее можно прочитать в документации к библиотеке a11y-dialog
: https://a11y-dialog.netlify.app/further-reading/dialog-element. Но на той же странице разработчики библиотеки пишут, что использование нативного элемента на настоящий момент вполне резонно.
Полифил же подключать необязательно — поддержка браузерами уже достаточно широкая, чтобы покрывать основную массу клиентов: caniuse.com пишет о 95.75% поддержки стандарта. Его стоит использовать, когда вам необходима поддержка совсем неактуальных браузеров типа Internet Explorer. Но если в вашем проекте требуется поддержка таких старых браузеров, скорее всего вы и так используете для них множество различных полифилов. В общем, моё мнение, что по умолчанию полифил для элемента <dialog>
подключать не нужно, так как стандарт уже вполне устоялся.
Ну, сделать модальный диалог только с CSS и HTML возможно и не очень сложно. И я хочу, чтобы мои страницы работали (хоть и без удобств) без JS. Так что, пожалуй, останусь пока на старых методах.
Желание хорошее. Но что насчёт доступности, модальности (::backdrop и inert), autofocus, закрытия по Esc, returnValue, top-layer и других возможностях, которые не реализуемы в решениях на CSS?
Ради мизерной доли процента случаев, когда js по каким-то причинам недоступен, жертвовать удобством для всех остальных. Не лучше ли использовать подходы прогрессивного улучшения в сочетании с динамическим импортом для апгрейда с решений без js на решения с js?
Так все эти функции можно сделать и на JS. Но они, если отсутствуют, не будут мешать основной функциональности. А вот, если использовать <dialog>
, то показать его можно только через JS. Хотя конечно можно попробовать сделать и параллельную поддержку через CSS. Но надо пробовать как все это уживется вместе...
Так все эти функции можно сделать и на JS.
Можно. Но <dialog>
предлагает многое из коробки без JS. Всё-же чем меньше его будет, тем лучше (меньше данных загружать по сети, не занимать основной поток лишним парсингом и исполнением).
А вот, если использовать
<dialog>
, то показать его можно только через JS.
На данный момент - да. Однако есть предложение Invokers от OpenUI, которое позволит декларативно открывать, в том числе, <dialog>
без JS. Chrome и Firefox уже взяли это в работу.
Тем не менее, открыть/закрыть <dialog>
- это пару строчек, а накрутить весь перечисленный функционал при помощи JS - сотни строчек.
Хотя, как вы говорите, возможно есть решение и через CSS, чтобы оно базовое работало.
Не согласен по поводу добавления aria-describedby
с ссылкой на блок с контентом. Ведь внутри диалога можно свободно перемещаться между элементами при помощи скринридера. Чтобы зачитать контент, достаточно перенести курсор скринридера к блоку с этим контентом.
А факт попадания в диалог, о чем оповестит скринридер благодаря встроенной роли dialog
и aria-modal
(для модальных диалогов), говорит пользователю о том, что он попал в некий изолированный блок, который требует его внимания. Поэтому пользователь изучит содержимое этого диалога, в том числе и контент.
Возможно, не обязательно добалять атрибут aria-describedby
именно для связи со всем контентом, но лучше добавить его хотя бы со ссылкой на блок с дополнительным описанием окна, чтобы скриндеры считали его сразу же после открытия окна, а не при наведении курсора. Я считаю, что в случае со вспомогательными технологиями стоит давать как можно больше информации.
Не совсем понятно, а как они будут рендерится если их будет несколько.
Можете попробовать в деле: https://codepen.io/alexgriss/pen/YzBgxwG
Как можно видеть, каждая новая открытая модалка будет рендериться на новом top layer, перекрывая остальные, вне зависимости от того, где в реальном DOM находится её элемент. А если попробовать открыть все модалки и начать закрывать их через клавишу Esc, то они будут закрываться по очереди, начиная с самой последней открытой.
Потрясающая статья! А то я по старинке модалку делал. Теперь буду знать и надо будет попробовать. Подпишусь, побольше таких статей про другие элементы. А то живёшь и не знаешь, что есть такие простые вещи.
Как использовать html-элемент <dialog>?