В наше время для различных сайтов нормой стали всевозможные всплывающие модальные окна — popup'ы — для регистрации, авторизации, информационные окна, — всевозможных форм и размеров. Также существует огромное количество плагинов к тому же jQuery для простого и удобного создания таких попапов — тот же Shadowbox, например.
Внешний вид, размеры и оформление таких попапов совершенно разнообразными — с оверлеем, тенюшками, анимациями — всего не счесть. Объединяет их только, пожалуй, тот факт, что обычно они выводятся в самом центре страницы — как по горизонтали, так и по вертикали. И центрирование это производится средствами JS. Я не буду вдаваться в подробности этих расчетов, опишу их лишь вкратце:
HTML-код попапа обычно имеет такую структуру:
И CSS (здесь и ниже я умышленно буду опускать написание некоторых свойств, необходимых лишь для некоторых браузеров и их версий, оставив лишь самое основное):
JS определяет браузер и версию браузера, и на основании этого высчитывает размеры рабочей области и размеры самого попапа (если они не заданы), а затем производятся нехитрые вычисления положения его левого верхнего угла (css-свойства left и top для .popup). Многие плагины также реагируют на изменение размеров страницы, пересчитывая всё это дело каждый раз, с тем, чтобы попап располагался точно в центре рабочей области.
Я по натуре своей перфекционист (знаю, порой это плохо), и частенько заморачиваюсь даже над мелкими деталями, пытаясь улучшить и добавить максимально возможную расширяемость этим деталям, и меня не мог не зацепить именно этот момент в работе всех этих плагинов. Возникла мысль, что всю работу по позиционированию попапа можно переложить с плеч JS на плечи самого браузера, то есть выполнять эту работу средствами CSS.
Этим и займёмся.
Ниже я приведу пример попапа, работающего во всех мажорных версиях основных браузеров. Для корректной его работы в IE<9 необходима некоторая экстра-разметка и хаки, потому детальное описание написания такого метода я опущу, а для интересующихся выложу полную версию.
Итак, у нас есть страница с кнопкой, при нажатии на которую должно всплывать модальное окно с некоторой информацией, а весь остальной контент должен затеняться оверлеем.
Для начала — HTML-код. Структура его будет немного отличаться от кода, указанного выше, почему — об этом ниже в статье; классы элементов останутся теми же:
И немного CSS:
Самый простой вариант. Ничего нового изобретать не нужно:
Отрицательные margin'ы в половину ширины и высоты — банально и скучно, ничего оригинального в этом нет. Идём дальше.
Сперва — выравнивание по горизонтали — это вроде бы проще. Если попап фиксированной ширины — то достаточно будет следующего:
На вертикальное выравнивание это никак не повлияет, и, к слову, если вам достаточно лишь горизонтального выравнивания, то на этом можно и остановиться, указав еще какой-нибудь верхний отступ попапа. Но нам этого мало! Идём дальше.
Вертикальное выравнивание. Здесь уже становится интересно. С такой задачей, конечно, без проблем справилась бы таблица или эмуляция таблицы с помощью display: table & display: table-cell, но заставить такое работать в старых IE — себе дороже. Таблица также отпадает — по понятным причинам.
Итак, margin уже отпадает — размеров мы не знаем. Вспоминаем, что же есть из свойств с подобными эффектами. Ага, text-align. Но только для инлайновых элементов. ОК. Кажется, сам Бог велел использовать display: inline-block — блочный элемент, к которому можно было бы применить свойства для инлайновых элементов. С поддержкой этого свойства у всех браузеров тоже всё, можно сказать, в порядке. Код становится примерно таким:
Остаётся вертикальное выравнивание — нам подойдёт vertical-align. В любой другой ситуации было бы также уместно использовать line-height, но поскольку у нас нет фиксированной высоты страницы (line-height в данном контексте), здесь использовать её нельзя. На помощь приходит один трюк с вертикальным выравниванием элементов неизвестных размеров. Я точно помню, что нашел этот способ на Хабре, но, к сожалению, не смог найти ссылку на тот топик. Заключается этот способ в следующем: добавляется inline-block элемент нулевой ширины и 100%-ой высоты родителя, который «расхлопывает» высоту строки до 100% высоты родителя, то есть до высоты рабочей области страницы. Сделаем это изящнее — вместо лишней разметки воспользуемся псевдоэлементами:
Осталось добавить полупрозрачное затемнение оверлея — с этим справится rgba. Всё! Теперь положение попапа регулируется только средствами браузера на уровне CSS.
Итоговый пример
Из замеченных минусов метода — порой возникают глюки с отображением в IE 6-7, в частности, при использовании флоатов.
Повторюсь — мой метод не избавляет от использования JS вообще, он лишь частично оптимизирует скорость работы всплывающих окон за счет переноса части нагрузки с JS на CSS.
Уверен, что метод можно улучшить — как визуально, так и изнутри, и буду рад любым идеям и предложениям по этому поводу, а также замечаниям по работе и отображению в различных браузерах.
UPD: По просьбам, добавил пример, работающий в IE7+ — http://jsfiddle.net/vend3tta/SE4tS/
Внешний вид, размеры и оформление таких попапов совершенно разнообразными — с оверлеем, тенюшками, анимациями — всего не счесть. Объединяет их только, пожалуй, тот факт, что обычно они выводятся в самом центре страницы — как по горизонтали, так и по вертикали. И центрирование это производится средствами JS. Я не буду вдаваться в подробности этих расчетов, опишу их лишь вкратце:
HTML-код попапа обычно имеет такую структуру:
<div class="popup__overlay"></div> <!-- Оверлей --><br/><div class="popup">...</div> <!-- Попап вместе с содержимым --> <br/>
И CSS (здесь и ниже я умышленно буду опускать написание некоторых свойств, необходимых лишь для некоторых браузеров и их версий, оставив лишь самое основное):
.popup__overlay {<br/> position: fixed;<br/> left: 0;<br/> top: 0;<br/> background: #000;<br/> opacity: .5;<br/> filter: alpha(opacity=50);<br/> z-index: 999<br/> }<br/>.popup {<br/> position: absolute;<br/> width: 20%;<br/> z-index: 1000;<br/> border: 1px solid #ccc;<br/> background: #fff<br/> } <br/>
JS определяет браузер и версию браузера, и на основании этого высчитывает размеры рабочей области и размеры самого попапа (если они не заданы), а затем производятся нехитрые вычисления положения его левого верхнего угла (css-свойства left и top для .popup). Многие плагины также реагируют на изменение размеров страницы, пересчитывая всё это дело каждый раз, с тем, чтобы попап располагался точно в центре рабочей области.
Я по натуре своей перфекционист (знаю, порой это плохо), и частенько заморачиваюсь даже над мелкими деталями, пытаясь улучшить и добавить максимально возможную расширяемость этим деталям, и меня не мог не зацепить именно этот момент в работе всех этих плагинов. Возникла мысль, что всю работу по позиционированию попапа можно переложить с плеч JS на плечи самого браузера, то есть выполнять эту работу средствами CSS.
Этим и займёмся.
Ниже я приведу пример попапа, работающего во всех мажорных версиях основных браузеров. Для корректной его работы в IE<9 необходима некоторая экстра-разметка и хаки, потому детальное описание написания такого метода я опущу, а для интересующихся выложу полную версию.
Итак, у нас есть страница с кнопкой, при нажатии на которую должно всплывать модальное окно с некоторой информацией, а весь остальной контент должен затеняться оверлеем.
Для начала — HTML-код. Структура его будет немного отличаться от кода, указанного выше, почему — об этом ниже в статье; классы элементов останутся теми же:
<div class="popup__overlay"><br/> <div class="popup"></div><br/></div> <br/>
И немного CSS:
.popup__overlay {<br/> position: fixed;<br/> left: 0;<br/> top: 0;<br/> width: 100%;<br/> height: 100%;<br/> z-index: 999<br/> }<br/>.popup {<br/> } <br/>
Фиксированные размеры
Самый простой вариант. Ничего нового изобретать не нужно:
.popup {<br/> left: 50%;<br/> top: 50%;<br/> width: 400px;<br/> height: 200px;<br/> margin-left: -200px;<br/> margin-top: -100px<br/> } <br/>
Отрицательные margin'ы в половину ширины и высоты — банально и скучно, ничего оригинального в этом нет. Идём дальше.
Размеры попапа зависят от содержимого
Сперва — выравнивание по горизонтали — это вроде бы проще. Если попап фиксированной ширины — то достаточно будет следующего:
.popup {<br/> margin: auto<br/> } <br/>
На вертикальное выравнивание это никак не повлияет, и, к слову, если вам достаточно лишь горизонтального выравнивания, то на этом можно и остановиться, указав еще какой-нибудь верхний отступ попапа. Но нам этого мало! Идём дальше.
Вертикальное выравнивание. Здесь уже становится интересно. С такой задачей, конечно, без проблем справилась бы таблица или эмуляция таблицы с помощью display: table & display: table-cell, но заставить такое работать в старых IE — себе дороже. Таблица также отпадает — по понятным причинам.
Итак, margin уже отпадает — размеров мы не знаем. Вспоминаем, что же есть из свойств с подобными эффектами. Ага, text-align. Но только для инлайновых элементов. ОК. Кажется, сам Бог велел использовать display: inline-block — блочный элемент, к которому можно было бы применить свойства для инлайновых элементов. С поддержкой этого свойства у всех браузеров тоже всё, можно сказать, в порядке. Код становится примерно таким:
.popup__overlay {<br/> position: fixed;<br/> left: 0;<br/> top: 0;<br/> width: 100%;<br/> height: 100%;<br/> z-index: 999;<br/> text-align: center<br/> }<br/>.popup {<br/> display: inline-block;<br/> vertical-align: middle<br/> } <br/>
Остаётся вертикальное выравнивание — нам подойдёт vertical-align. В любой другой ситуации было бы также уместно использовать line-height, но поскольку у нас нет фиксированной высоты страницы (line-height в данном контексте), здесь использовать её нельзя. На помощь приходит один трюк с вертикальным выравниванием элементов неизвестных размеров. Я точно помню, что нашел этот способ на Хабре, но, к сожалению, не смог найти ссылку на тот топик. Заключается этот способ в следующем: добавляется inline-block элемент нулевой ширины и 100%-ой высоты родителя, который «расхлопывает» высоту строки до 100% высоты родителя, то есть до высоты рабочей области страницы. Сделаем это изящнее — вместо лишней разметки воспользуемся псевдоэлементами:
.popup__overlay:after {<br/> display: inline-block;<br/> width: 0;<br/> height: 100%;<br/> vertical-align: middle;<br/> content: ''<br/> } <br/>
Осталось добавить полупрозрачное затемнение оверлея — с этим справится rgba. Всё! Теперь положение попапа регулируется только средствами браузера на уровне CSS.
Итоговый пример
Из замеченных минусов метода — порой возникают глюки с отображением в IE 6-7, в частности, при использовании флоатов.
Повторюсь — мой метод не избавляет от использования JS вообще, он лишь частично оптимизирует скорость работы всплывающих окон за счет переноса части нагрузки с JS на CSS.
Уверен, что метод можно улучшить — как визуально, так и изнутри, и буду рад любым идеям и предложениям по этому поводу, а также замечаниям по работе и отображению в различных браузерах.
UPD: По просьбам, добавил пример, работающий в IE7+ — http://jsfiddle.net/vend3tta/SE4tS/