Еще один способ вертикального выравнивания в CSS
26 Apr, 2007Много копий сломано на ниве вертикального выравнивания без таблиц. Однако недавно я узнал о еще одном более простом способе. Этот пост, перевод статьи уважаемого мною Gunlaug о вертикальном выравнивании без дополнительного HTML и с помощью правда другого зла.
Оригинальная статья: fully centered across browser-land…
Задача
Отцентрировать что-нибудь вертикально внутри какого-либо элемента(экрана например).Возьмем такой вот HTML:
- <div id="out">
- <p id="centered" >...</p>
- </div>
Для всех современных броузеров(не IE) это достигается двумя простыми строками:
- #out{
- height:500px;
- display:table-cell;
- vertical-align:middle;
- }
IE+expression=нормальный броузер
Для эмуляции будем использовать expression (маленькие кусочки джаваскрипта который можно внедрять в CSS и работают лишь в ИЕ). Вот что сэмулирует нам вертикальное выравнивание в ИЕ для элемента #centered внутри другого элемента:#centered { margin-top: expression(((outer.offsetHeight/2) -parseInt(offsetHeight)/2) <0 ? "0" : (outer.offsetHeight/2) -(parseInt(offsetHeight)/2) +'px') ; }(видно как внутри ЦСС правил для #centered мы получаем его высоту по айдишнику
centered.offsetHeight
и высоту div#outer)
Или если мы выравниваем внутри body
:
#centered{ margin-top: expression(( document.documentElement.offsetHeight/2) -(parseInt(offsetHeight)/2) <0 ? "0" : (document.documentElement.offsetHeight/2) -(parseInt(offsetHeight)/2) +'px') ;Это правило определяет высоту родительского элемента(или body) и высоту центрируемого элемента - после чего добавляет нужный margin-top для вертикального центрирования элемента.
Был предложен также метод для классов:
margin-top: expression((parentNode.offsetHeight - this.offsetHeight)<0 ? "0" : (parentNode.offsetHeight - this.offsetHeight)/2 + "px")
(parseInt убран для наглядности)
Как это работает
- document.documentElement.offsetHeight/2
определяет высоту body и делит ее на 2. Это дает нам отступ ровно в половину высоты экрана - -(parseInt(offsetHeight)/2))
Определяет высоту самого центрируемого блока. Отнятое от высоты родителя дает нам конечный margin-top - <0 ? "0" :
Если полученная разница отрицательная, то отступу присваивается значение 0. - <0 ? "0" :
Если же полученный результат больше либо равен 0, то повторяем вычисления и берем margin-top равный полученному значению для вертикального центрирования
Словами
Что бы понять откуда взялись все эти вычисления. Представьте что наш блок отцентрирован по вертикали внутри другого блока. Вот так:И теперь нам нужно посчитать расстояние от верха родительского блока - до отцентрированного элемента(x-y). Очевидно для этого нам придется отнять от половины высоты родителя(x), половину высоты отцентрированного(y). Вычисление этого расстояния и происходит в скрипте, после чего оно присваивается в качестве margin-top, что по сути визуально центрирует блок по вертикали.
Конечно это своеобразная дилемма - "3 обертывающих DIV" или "expression", зависит от случая, но как по мне, выбор тут однозначен ;).
Если Вам нужна валидность, да и просто ради красоты, эту строку для IE стоит перенести в отдельный CSS файл(СС), либо каким то образом оградить от других броузеров.
Ссылки
- Оригинал fully centered across browser-land… статья Gunlaug Sørtun про этот прием и центрирование вообще (там же в правой колонке несколько примеров)
- Пример центрирования в блоке
- Пример центрирования на экране
- Пример Gunlaug, для ИЕ там выводятся промежуточные числа вычислений..
- Информация об определении размеров блока на MSDN
- Информация о методе parseInt
- Вариант для классов, а не айди
68 комментариев к “Еще один способ вертикального выравнивания в CSS”