Вертикальное выравнивание

Автор: Евгений Рыжков Дата публикации: 20.08.2009
Последнее обновление: 14.12.2010

Задача

Сделать вертикальное выравнивание текста или элемента по центру относительно родителя, используя блочную верстку.

Теория

При использовании табличной верстки, не составляло труда выровнять, элементы или текст внутри ячейки, достаточно было задать свойство vertical-align: middle.

Как оказалось, элементы уровня блок не могут, аналогично ячейкам таблицы, вертикально выравнивать. Но CSS позволяет изменять поведение элементов (свойство display), например, сделать блок, который будет себя вести как ячейка таблицы — display: table-cell. Казалось бы, вот оно решение, простое и понятное, осталось добавить vertical-align: middle и можно наслаждаться результатами своих трудов. Но есть горяче любимый всеми веб-разработчиками браузер, который не даст так быстро ликовать — Interner Explorer. IE6 и IE7 не поддерживает значение свойства display table-cell. Приходится прибегать к программному решению (expression) для этих браузеров.

Решение

Делаем следующие:

  • блоку-родителю, внутри которого будет вертикальное выравнивание, задаем высоту (height), display: table-cell и vertical-aling: middle — этого для большинства браузеров будет достаточно
  • элементу, который будем выравнивать добавляем expression — скрипт, который при загрузке страницы, определит какой ему нужно сделать отступ сверху (в зависимости от высоты родителя и своей высоты), чтобы оказаться вертикально выровненным по центру (если нам нужно выровнять текст, его придется заключить в дополнительный контейнер). Этот трюк предназначен для IE6 и IE7

Для примера выровняем абзац текста:

<div class="parent">
<span>абзац какого-то жутко интересного и полезного текста</span>
</div>

CSS:

.parent {
background: #3399FF;
display: table-cell;
height: 200px;
vertical-align: middle;
color: #fff;
width: 400px;
}
* html .parent span {
/* хак для ие6 */
display: block;
z-index: expression( /* оптимизированный expression, который сработает только при загрузке страницы */
runtimeStyle.zIndex = 1,
this == ((200/2)-parseInt(offsetHeight)/2) <0 ? style.marginTop="0" : style.marginTop=(200/2)-(parseInt(offsetHeight)/2) +'px');
}
*:first-child+html .parent span {
/* хак для ие7 */
display: block;
z-index: expression(
runtimeStyle.zIndex = 1,
this == ((200/2)-parseInt(offsetHeight)/2) <0 ? style.marginTop="0" : style.marginTop=(200/2)-(parseInt(offsetHeight)/2) +'px');
}

Результат. По этой же схеме можно выравнивать любой элемент внутри, например изображение, плюс поместим ее в центр по горизонтали.

Проверено в:

Заметки

  • родитель не должен быть плавающим (float: left/right), т.к. плавающие элементы автоматически становятся блочными
  • родитель не должен быть с абсолютным или фиксированным позиционированием (position: absolute/fixed)
  • элемент, который выравниваем по центру (дочерний, в примерах это span и img) должны быть блочными, нужно для IE6 и IE7, т.к. отступы сверху/снизу работают только для блочных элементов

Метод строчных блоков

Update 14.12.2010 by Александр Головко, Денис Шутько.

Этот вариант так же использует display: table-cell; и vertical-align: middle; для всех нормальных браузеров. Отличие в том, что для IE6-7 применяем другое лекарство — добавляем строчный блок, который и обеспечит выравнивание по центру. Чтоб не засорять код лишним блоком, добавим его с помощью эмуляции псевдоэлемента before.

<div class="parent">
	<div class="child">абзац какого-то жутко интересного и полезного текста</div>
</div>
.parent {
	display: table-cell;
    vertical-align: middle; 
    height: 400px;
	width: 350px;
	border: 1px solid #539127;
}
/* Все стили ниже комментария нужны только для IE6-7. Если есть возможность - выносим их в отдельный CSS */
.parent {
	z-index: expression(runtimeStyle.zIndex = 1, insertAdjacentHTML('beforeEnd', '
')); } .auxiliary { display: inline-block; vertical-align: middle; width: 0px; height: 100%; } .child { display: inline-block; } .child, .auxiliary { vertical-align: middle; display: inline; }

Демо-пример.

Проверено в:

  • IE 6-8
  • Firefox 3.5
  • Opera 10
  • Chrome 7
  • Safari 3.1

Метод без expression

Update 18.12.2010 by Александр Головко, Надежда.

Если использовать дополнительный контейнер — можно обойтись без expression. Правда, при этом придется, опять таки, разделить стили для IE младших версий и нормальных браузеров.

<div class="parent">
	<div class="container">
		<div class="child">абзац какого-то жутко интересного и полезного текста</div>
	</div>
</div>
.parent {
	position:relative;
	display:table;
    height: 400px;
	width: 350px;
	border: 1px solid #539127;
	vertical-align: middle; 
	text-align: center;
}
.container {
	width:100%;
	display:table-cell;
	vertical-align:middle;
	position:relative;
	text-align:center;
}
.child{
	display:inline;
	vertical-align:middle;
}

Стили для IE6-7:

.parent {
	overflow:hidden
}
.parent,
.container {
	display:block
}
.container {
	top:50%;
	left:0;
}
.child {
	top:-50%;
	position:relative;
	display:block
}

Демо-пример.

Проверено в:

  • IE 6-8
  • Firefox 3.5
  • Opera 10
  • Chrome 7
  • Safari 3.1

Плюсы:

  • нет expression;
  • нет ограничения на родителя, как в первом методе (т.е. может быть плаваюшим или с абсолютным/фиксированным позиционированием).

Минус

  • дополнительный контейнер в HTML.