Как стать автором
Обновить

Комментарии 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, то они будут закрываться по очереди, начиная с самой последней открытой.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории