3 ноября 2009

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

Вертикальное выравнивание в 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;
}

Вот и вся хитрость. При желании, вы можете посмотреть на сверстанный блок переменной высоты с отцентрованным содержимым.

Дополнительную информацию по вертикальному выравниванию блока переменной высоты можно получить тут.

С уважением, Андрей Морковин.

Плюсануть
Поделиться
Отправить
Класснуть
Линкануть
Запинить