Модальные диалоги (pop-up) на HTML

Часть 1. Теория

Сейчас использование модальных и не только диалогов на веб-сайтах является вполне нормальным явлением, в следствии чего нам доступна масса уже готовых контролов как для asp.net/…. (подставьте сюда ту технологию, которую вы используете в своих проектах), так и множество плагинов для популярных javascript-фреймворком, таких как jquery, moo tools, prototype и других. Для упрощения договоримся, что здесь под контролом я буду иметь в виду все что, что в итоге превращается в html-код и выглядит как привычное нам модальное диалоговое окно.Реализация диалогового окна на html выглядит следующим образом:

  • в какой-то элемент (например, ) помещается весь контент диалогового окна и ставится ему свойства display:none; z-index:100; position:absolute;
  • создается “фоновый” элемент для создания эффекта модальности с такими свойствами: background-color:gray; position: absolute; width: 100%; height: 100%;     z-index: 90; display:block; opacity:.32; top:0; left:0;display:none; (например, ).  - этот пункт нужен только для создания модального диалога;
  • при отображении диалогового окна мы меняем у нашего контейнера и фона свойства display на значение block и видим эффект (модального) диалогового окна.

Пример простого pop-up’а находится в файле simple-popup.htmlВсе модальные окна, реализованные на HTML, которые встречал работали по описанному алгоритму. Изменения были лишь в удобстве работы с ними и набором дополнительных фич, таких как: drag-n-drop, поддержка тем, обработчики событий и др.Я всегда использовал этот алгоритм до того момента, как мне не пришлось делать возможность навигации по кнопкам внутри модального диалога с помощью клавиатуры. Для примера, рассмотрим работу диалого, реализованного в файле simple-popup-with-input.html.

При нажатии на кнопку show показывается наш модальный диалог. При этом, мы не можем мышкой перейти на поле ввода вне диалога или кликнуть по кнопке show еще раз до закрытия текущего. С первого взгляда все кажется вполне работоспособным. Но кажется это только до нажатия “магической” (magic!) кнопки tab. И тут мы попадаем на наши поля ввода в таком порядке:

  • кнопка show;
  • поле ввода за кнопкой show;
  • поле ввода на диалоге
  • кнопка hide;
  • элементы управления браузера;
  • и так по кругу…

Здесь мы видим, что модальный диалог никакой не модальный, а только кажется таковым.

Как это работает?Диалоги на HTML реализуются с помощью слоев отображения элементов. По умолчанию, у нас есть только один слой, т.е. свойство z-index у всех элементов одинаково и равно 0. Для создания нового слоя необходимо выставить свойство z-index в 1, 2, и т.д. В нашем примере, у элементов, не входящих в диалог, z-index равен 0, у фона диалога z-index равен 90, а его высота и ширина равняется 100%, что соответствует ширине и высоте окна браузера, из-за чего он визуально перекрывает элементы, у которых z-index < 90 и складывается впечатление модальности. Последним у нас идет элемент с содержимым диалога, у которого z-index равен 100 (максимальное, в нашем случае, значение), что позволяет нам отобразить его на “переднем” слоем.

Из-за слоев, мы не можешь попасть мышкой на кнопку show, но прекрасно можем добраться до нее с помощью клавиатуры (кнопка tab), а также вводить данные в текстовое поле вне диалога. Получается такой себе полу-модальный диалог с неправильной навигацией с клавиатуры.

В следующей части я расскажу как можно обойти данную проблему и покажу прототип модального диалога, в котором корректно работает tab order.

popup.zip (25,42 kb)

Tags

.net .net-framework .net-framework-3.5 agile ajax ajax-control-toolkit ampq ansible apache asp.net asp.net-mvc automation axum babel bash benchmark blog blog-engine bootstrap buildout c# cache centos chrome ci cinder ckan cli cloud code-review codeplex community config debugger deface dependencies development-environment devices devstack devtime disks django dlr dns docker dockerimage dos easy_install elmah encoding environment-variables error event events everything-as-a-code exception exceptions fabrik firefox flask foreach forms fstab gae gcc gerrit git github go google google-app-engine grep hack hacked hardware headless horizon hound html hugo iaas ienumerable iis internet iptables iron-python ironic iscsi java-script javascript jenkins jquery js jsx k8s kharkivpy kiss kombu kubernetes kvm kyiv lettuce libvirt linux lio loci logging loopback losetup lvm mac-os macos mercurial microsoft microsoft-sync-framework mobile mono ms-office msbuild networking news nginx npm npx offtopic oop open-source open-xml opensource openstack openvswitch os packages paraller-development patterns-practices performance php pika pip plugins pnp podcast popup postgresql profiler project protocols proxy pycamp pycharm pycon pykyiv pylint pypi python python-3 qcow quantum qumy rabbitmq rar react reactjs refactoring rfc rhel search-engine security selenium server shell silverlight socket software-engineering source-control sourcegear-vault sources sql sql-server sql-server-express sqlalchemy ssh static-site sublimetext svg tests tgt tipfy todo tornado typescript uapycon ui uneta unit-tests upgrades usability vim virtualenv visual-studio vitrage vm vue.js vuejs web-development web-server web-service web_root webpack webroot windows windows-live word-press x32 x64 xcode xml xss xvfb интернет-магазин книги

Recent posts

Go 1.18: new features

Всё будет Kubernetes

2022 Relaunch

Everyday Blogging

I don't want this CI


Archives

2022 (3)
2019 (73)
2018 (2)
2017 (3)
2016 (2)
2015 (3)
2014 (5)
2013 (17)
2012 (22)
2011 (36)
2010 (25)
2009 (35)
2008 (32)
2007 (2)