Вертикальное выравнивание в div. Бонус: условные комментарии

Сегодня, уважаемый читатель, мы с вами разберемся с проблемой вертикального выравнивания в блоке div.
Скорее всего вы уже знаете о существовании замечательного свойства CSS vertical-align. И сам Бог велел нам пользоваться для вертикального выравнивания именно этим свойством (не зря же оно носит такое, говорящее само за себя, название).
Постановка задачи: Необходимо выровнять содержимое блока переменной высоты по центру относительно вертикали.
Теперь приступим к решению поставленной задачи.
И так, у нас есть блок, высота его может меняться:
<div>Содержимое блока</div>
Первое, что приходит в голову – это сделать следующий финт:
<div style=»vertical-align: middle»>Содержимое блока</div>
Есть все основания предполагать, что фраза Содержимое блока выровняется по центру высоты div-контейнера.
Но не тут-то было! Никакого ожидаемого выравнивания по центру таким образом мы не добьемся. А почему? Казалось бы все указано правильно. Оказывается вот в чем загвоздка: свойство vertical-align можно применять только для выравнивания содержимого ячеек таблиц или для выравнивания строчных элементов друг относительно друга.
По поводу выравнивания внутри ячейки таблицы, я думаю, все понятно. А вот другой случай со строчными элементами я поясню.
Вертикальное выравнивание строчных элементов
Предположим есть у вас строка текст, которая разбита строчными тегами <span> на части:
<span id="perviy">Вас</span> <span id="vtoroy">приветствует</span> <span id="tretiy">кусок</span> текста!
Под строчным тегом понимается контейнер, появление которого не приводит к переносу содержимого на новую строку.
Действие же блочного тега приводит к переносу содержимого контейнера на новую строку.
<div> – это блочный тег. Если мы заключим куски текста в блоки <div>, то каждый из них окажется на новой строке. Используя тег <span>, который, в отличие от <div>, является строчным, переноса контейнеров на новую строку не будет, все контейнеры <span> останутся в одной строке.
Контейнер <span> удобно использовать при задании части текста особого форматирования (выделение цветом, другим шрифтом и т.д.)
Для контейнеров <span> применим следующие свойства CSS:
#perviy{
vertical-align:sub;
}
#vtoroy{
vertical-align:3px;
}
#tretiy{
vertical-align:-3px;
}
В результате строка текста будет иметь вот такой вид:

Это и есть ничто иное, как выравнивание строчных элементов по вертикали, и свойство CSS vertical-align с этой задачей прекрасно справляется.
Мы немного отвлеклись, теперь возвращаемся к нашей основной задаче.
Выравнивание по вертикали в div-контейнере
Не смотря ни на что, для выравнивания внутри div-контейнера мы будем использовать свойство vertical-align. Как я уже говорил, данное свойство можно использовать в случае выравнивания строчных элементов (этот случай мы подробно рассмотрели выше и для выравнивания в div-контейнере он нам не подходит); остается лишь использовать тот факт, что vertical-align работает для ячеек таблицы.
Как же мы сможем это использовать? У нас же нет таблицы, мы работаем с div-контейнером.
Ха, оказывается очень просто.
CSS-свойство display позволяет превратить наш блок div в ячейку таблицы, сделать это можно легко и непринужденно:
Пусть у нас есть div класса textalign:
<div class=»textalign»>Содержимое блока</div>
Для данного блока указываем следующее CSS-свойство:
.textalign{
display: table-cell;
}
Эта CSS-инструкция чудесным образом превратит наш блок div в ячейку таблицы, визуально никак его не изменив. А для ячейки таблицы мы сможем применять свойство vertical-align в полной мере и будет работать желаемая центровка по вертикали.
Однако, все так просто закончится не может. У нас же есть замечательный браузер IE. Он не умеет работать со свойством display: table-cell (предлагаю вам ознакомится с табличкой, иллюстрирующей работоспособность данного CSS-свойства в разных браузерах на сайте htmlbook.ru). Поэтому нам придется идти на различные ухищрения.
Существует множество способов добиться выравнивания в div-контейнере для всех браузеров:
- Способ с применением дополнительного вспомогательного div-котнейнера
- Способ с использованием expression-а. Связан он с хитрым вычислением высот блоков. Без знания JavaScript тут не обойтись.
- Использование свойства line-height. Данный способ подходит только для вертикального выравнивания в блоке известной высоты, а значит в общем случае не применим.
- Использование абсолютного и относительного смещения содержимого в случае браузера IE. Мне этот способ кажется наиболее понятным и простым. Кроме того, он реализуем для div-контейнера переменной высоты. На нем мы остановимся подробнее.
Как вы понимаете, нам остается решить проблему вертикального выравнивания в IE, связанную с его непониманием свойства display: table-cell (ни IE6, ни IE7, ни IE8 с этим свойством не знакомы). Поэтому воспользовавшись условным комментарием специально для браузеров семейства IE мы укажем другие свойства CSS.
Условный комментарий
Конструкция вида:
<!--[if IE]> ... Инструкции, действующие только в случае выполнения условия в квадратных скобках ... <![endif]-->
называется условным комментарием (будьте внимательны, вид условного комментария должен полностью соответствовать приведенному примеру, с точностью до пробела).
Инструкции, содержащиеся в подобном условном комментарии будут выполнены только в случае, если браузер, интерпретирующий данный код, принадлежит к семейству IE.
Вы можете более подробно познакомится с условными комментариями.
Таким образом, используя условный комментарий, мы сможем спрятать кусок кода от всех браузеров кроме IE.
Запомнили, пошли дальше.
Решение задачи
Из-за всей этой петрушки нам нужно будет снабдить наш HTML-код двумя дополнительными контейнерами. Вот каким образом будет выглядеть наш блок с текстом:
<div class="textalign"> <div> <span>Это какой-то проверочный текст. <br />Он состоит из двух строк.</span> </div> </div>
Для div-контейнера класса textalign задаются CSS-свойства, которые выравнивают его содержимое по вертикали для всех нормальных браузеров (кроме IE, разумеется):
display: table-cell; vertical-align: middle;
И еще два свойства, которые задают ширину и высоту для блока:
width:500px; height: 500px;
Этого вполне достаточно для выравнивания содержимого контейнера по центру относительно вертикали, во всех браузерах кроме IE.
Теперь начинаем дописывать свойства, связанные с выравниванием для браузеров семейства IE (именно для них мы использовали дополнительные блоки div и span):
Обращаемся к тегу div внутри блока класса textalign. Для этого нужно указать сначала название класса, а потом, через пробел, тег, к которому мы обращаемся.
.textalign div{
position: absolute;
top: 50%;
}
Такая конструкция означает: для всех тегов div внутри блока с классом textalign применить перечисленные свойства.
Если все оставить так как есть, то div-контейнер, который находится внутри блока textalign, будет позиционироваться относительно верхнего левого угла браузера. Нам же нужно, чтобы смещение на 50% по вертикали произошло относительно родительского блока. Для этого достаточно применить CSS-свойство position: relative блоку textalign. Об этих особенностях я подробно рассказываю в видеоуроке по работе с блоками div.
Соответственно, стили заданные для блока textalign видоизменяются:
.textalign{
display: table-cell;
vertical-align: middle;
width:500px;
height: 500px;
position: relative;
}
Теперь левая верхняя точка текстового блока смещена вниз на 50%.
Для пояснения происходящего я нарисовал иллюстрацию:

Как видно из картинки, определенного прогресса мы добились. Но это еще не все! Верхняя левая точка желтого блока действительно сместилась на 50% вниз, относительно родительского (фиолетового) блока. Но нам-то нужно, чтобы на пятидесяти процентах высоты фиолетового блока находился центр желтого блока, а не его верхняя левая точка.
Теперь в ход пойдет тег span и его относительное позиционирование:
.textalign span{
position: relative;
top: -50%;
}
Тем самым, мы сместили желтый блок вверх на 50% его высоты, относительно начального положения. Как вы понимаете, высота желтого блока равна высоте центрируемого контента. И последняя операция со span-контейнером расположила наш контент посередине фиолетового блока. Ура!
Немного подшаманим
Перво-на-перво нам нужно спрятать петрушку от всех нормальных браузеров и открыть ее для IE. Сделать это можно, конечно же, при помощи условного комментария, не зря мы с ним знакомились:
<!--[if IE]>
<style type="text/css">
.textalign div{
position: absolute;
top: 50%;
}
.textalign span{
position: relative;
top: -50%;
}
</style>
<![endif]-->
Есть небольшая проблемка. Если центруемый контент слишком высокий, то это приводит к неприятным последствиям: появляется лишняя высота вертикальной прокрутки.
Решение проблемы: нужно добавить свойство overflow: hidden блоку textalign.
Детально познакомиться со свойством overflow можно в видеоуроке по работе с блоками div.
Окончательный вид CSS-инструкций для блока textalign имеет вид:
.textalign{
display: table-cell;
vertical-align: middle;
width:500px;
height: 500px;
position: relative;
overflow: hidden;
border: 1px solid black;
}
При желании, вы можете посмотреть HTML и CSS пример всего вышесказанного.
Прошу пардону, забыл упомянуть один важный момент. Если вы будите пытаться задавать высоту блока класса textalign в процентном соотношении, то у вас ничего не выйдет.
Центровка в блоке переменной высоты
Очень часто встречается необходимость задать высоту блока класса textalign не в пикселах, а в процентах от высоты родительского блока, и выровнять содержимое div-контейнера по середине.
Загвоздка в том, что для ячейки таблицы невозможно этого сделать (а ведь блок класса textalign превращается именно в ячейку таблицы, благодаря свойству display:table-cell).
В этом случае необходимо использовать внешний блок, для которого указано CSS-свойство display:table и уже для него задавать процентное значение высоты. Тогда вложенный в него блок, с CSS-директивой display:table-cell, благополучно унаследует высоту родительского блока.
Для того, чтобы в нашем примере реализовать блок переменной высоты, мы немного подредактируем CSS:
Классу textalign мы изменим значение свойства display с table-cell на table и убирем директиву выравнивания vertical-align: middle. Теперь мы смело можем изменить значение высоты с 500 пикселов на, например, 100%.
Таким образом, CSS-свойства для блока класса textalign будут иметь следующий вид:
.textalign{
display: table;
width:500px;
height: 100%;
position: relative;
overflow: hidden;
border: 1px solid black;
}
Остается реализовать центрирование содержимого. Для этого div-контейнеру, вложенному в блок класса textalign (это тот самый желтый блок на рисунке), необходимо задать CSS-свойство display:table-cell, тогда он унаследует высоту в 100% от родительского блока textalign (фиолетовый блок). И нам ничто не помешает выровнять содержимое вложенного div-контейнера по центру свойством vertical-align: middle.
Получаем еще один дополнительный список CSS-свойств для блока div, вложенного в контейнер textalign.
.textalign div{
display: table-cell;
vertical-align: middle;
}
Вот и вся хитрость. При желании, вы можете посмотреть на сверстанный блок переменной высоты с отцентрованным содержимым.
Дополнительную информацию по вертикальному выравниванию блока переменной высоты можно получить тут.
С уважением, Андрей Морковин.
Похожие материалы:
Отзывов: 40 на «Вертикальное выравнивание в div. Бонус: условные комментарии»
-
Что такое !DOCTYPE - подробно о HTML-стандартах — 23.11.2009 в 15:12
-
Способы вертикального выравнивания в div. | S Blog — 24.08.2010 в 23:05














, 04.11.2009 в 09:58
А как быть с блоками не фиксированной высоты?
, 04.11.2009 в 10:50
Центровка не привязывается к высоте блока. Приведенному варианту все равно, какая там высота.
, 04.11.2009 в 14:00
Кажется я понял, в чем была проблема. Дописал часть под названием «Центровка в блоке переменной высоты». Спасибо за комментарий, упустил этот факт из виду.
, 04.11.2009 в 21:10
) да я как бы об этом.
Теперь надо проверить, но я думаю будет работать, когда например в боксе слева имаджа (допустим 500х500) а справа от нее текст выравнивается по вертикали.
, 20.06.2011 в 17:52
с доктайпом xhtml не катит. не хочет он высоту в процентах
, 04.11.2009 в 11:11
Мне нравится этот способ. Надо как-то его запомнить =) Такие штуки мне еще, по-моему, не приходилось делать.
, 04.11.2009 в 14:07
Да, способ простой и понятный, этим он мне нравится больше все остальных извращений.
, 04.11.2009 в 11:43
раньше не получалось выровнять в ie по вертикали, теперь знаю))
спасибо за способ
, 04.11.2009 в 14:07
Рад, что материал полезен.
, 04.11.2009 в 12:18
Классно! Спасибо.
, 04.11.2009 в 14:08
Я старался
, 04.11.2009 в 13:55
ие8 понимает display:table-cell (http://msdn.microsoft.com/en-us/library/ms530751%28VS.85%29.aspx), поэтому ему заглушка не нужна. кроме того, можно унести ненужные стили .textalign{position: relative; overflow: hidden;} в conditional comments, т.к. они нужны только ие6-7
, 04.11.2009 в 14:05
Я проверял на http://browsershots.org/, отключив заглушку для IE8 (использовал меньше либо равно IE7). Центровка не произошла. Вы проверяли? У меня нет установленного IE8, поэтому по человечески проверить не могу, доверяю browsershots.
Совершенно согласен, .textalign{position: relative; overflow: hidden;} самое место в conditional comments. Спасибо.
, 04.11.2009 в 15:14
Да, проверила на чистой восьмерке при условии [if lt IE 8] display:table-cell работает. В compatibility view отрабатывается как у 7. А на http://browsershots.org/ действительно не работает в 8…
Кроме того, не совсем понимаю, зачем указывать у .textalign {display:table} для переменной высоты. Согласно Anonymous table objects http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes это необязательно и без этого работает: «ячейки» растягиваются в зависимости от содержимого, height лишь задает минимальную высоту. Хотя, если уж «лишний» элемент из-за ие6-7 есть, то пусть будет и table
Еще для border-collapse:collapse может пригодиться
, 05.11.2009 в 15:26
По поводу .textalign {display:table}:
Сделано это для того, чтобы можно было растянуть ячейку без всякой зависимости от высоты содержимого.
, 04.11.2009 в 15:24
Поправка: на http://browsershots.org/ тоже нормально в 8, не туда посмотрела
, 04.11.2009 в 16:31
Я так и не понял, понимает IE8 display:table-cell или нет?
, 04.11.2009 в 16:55
да, понимает
, 04.11.2009 в 20:49
Еще раз перепроверил скрин с сайта http://browsershots.org/. ИЕ8 не понял директивы display:table-cell, поэтому применяю условный комментарий для всех браузеров семейства ИЕ.
Ваше мнение базируется на прочитанном или проверяли самостоятельно? Если проверяли, то как?
, 04.11.2009 в 17:19
Огромное спасибо за статью! Страницу в избранное, РССку в ридер!
, 04.11.2009 в 20:50
Вот это правильный подход
, 09.11.2009 в 16:04
Блин. А вот с комментами надо чёто делать. Выглядят ужасно, имхо. Все эти деревья вносят полнейший хаос в комментарии.
, 09.11.2009 в 16:09
А что с ними делать? Можно просто отключить деревья вообще, но так не возможно будет проследить ветвь обсуждения.
Я, лично, за отслеживание ветви обсуждения вопреки хаосу.
, 09.11.2009 в 16:52
Лучше имхо писать перед комментом Имя того, к кому обращаешься. Хотя… можно подумать и сделать как-то альтернативно. Чтобы удобно было и ветвь прослеживалась легко.
, 04.11.2009 в 22:19
Классно! Попал случайно, через grabr, но радостно подписываюсь, ибо люблю подобные фокусы. Сам недавно с версткой возился, что и описал в http://it.sander.su/design-tricks.php
, 04.02.2011 в 00:42
где трюки то там?)))
помойму ты в ксс научился тока работать.
за статью респект.
, 05.11.2009 в 11:19
Мы с takobus все же выяснили поддерживает или нет IE8 свойство display:table-cell.
takobus пишет:
Теперь понятно, display:table-cell и прочие табличные значения display в ie8 не работают:
— в quirks mode;
— с доктайпом HTML 4.01 Transitional.
Работают с доктайпами:
— HTML 4.01 Strict;
— XHTML 1.0, 1.1;
— HTML5
Вы тестировали с HTML 4.01 Transitional, а я с XHTML 1.0 Transitional, использую по умолчанию.
, 05.11.2009 в 15:28
Спасибо, takobus! Теперь я буду в курсе (и не только я, а и все остальные, кто читает комментарии к статьям).
, 18.12.2009 в 00:23
Теперь будем использовать только HTML 4.01 Strict
, 31.01.2010 в 18:08
Огромное спасибо за пункт «Центровка в блоке переменной высоты»!!! то что нужно!!!
сначала не могла понять почему же у меня не получается, но потом поняла, что все из-за класса .textalign div. ко всем остальным divам в этом слое тоже применяются все свойства (я выровнила так весь сайт a-design.su). Поэтому чтобы другие пользователи вашего блога не тупили как я))), прошу дать этому слою название:
Это какой-то проверочный текст. Он состоит из двух строк.
еще раз БОЛЬШОЕ СПАСИБО!!!!)))
, 30.06.2010 в 11:21
Здравствуйте Андрей!
Как выяснилось, приведённый в иллюстрации метод работает не для всех доктайпов…
Предлагаю убрать «лишние» стили и всю css сократить до вот такой:
.textalign{
width:500px;
height: 500px; /*можно и в %%*/
position: relative;
overflow: hidden;
border: 1px solid black;
}
.textalign div{
position: absolute;
top: 50%;
}
.textalign span{
position: relative;
top: -50%;
}
Т.е. для всех браузеров будем использовать тот метод, который применяем для нужного нам выравнивания в IE6. Этих стилей достаточно, они поддерживаются всеми браузерами и удовлетворяют всем доктайпам. Да и условными комментами пользоваться не прийдётся.
По крайней мере, в моём случае, с приведённой разметкой сработало отлично — прошло все проверки.
Есть мнения?
, 30.06.2010 в 14:41
Прошу прощения, если высота родителя задана в %%, то приведённые в предыдущем моём комменте стили не срабатывают для XHTML.
, 25.10.2010 в 15:29
Спасибо! Красиво и логично, проще для понимания чем воркэраунды на Хабре.
, 29.11.2010 в 05:25
нифига не помогло(
дисплей тебл-целл сделал, позишн слоя — абсолют… так и болтается прижатый текс к топовому краю, задаётся тегом к меня, но это наверное ничего не меняет??
, 13.12.2010 в 16:39
Тоже парился, вроде все по инструкции, а не опускается текст. Всему виной оказался float: left блока к которому я применял вертикальное выравнивание. Пришлось добавить еще один блок и все заработало.
, 13.12.2010 в 19:38
полный код с фиксом плз в студию!
для меня вопрос еще открыт
, 13.12.2010 в 20:05
блин, коммент обрезался, дайте контакты я скину
, 21.10.2011 в 11:45
Поясните, куда надо вставить условный комментарий?