Но когда высота блока неизвестна и там может быть что угодно, такой способ не подходит. Что в таком случае делать?
Всё просто: есть атрибут display:table-cell, который наследует свойства табличных ячеек (как положительные, так и отрицательные, но об этом позже).
Т.к. он наследует таблицы, в нем работает свойство vertical-align:middle. Для того чтобы задать такому блоку размеры в процентах (например height:100%, что нам понадобиться) его необходимо было поместить в блок с атрибутом display:table с заданным размером, т.к. display:table-cell может брать относительные размеры только от display:table а тот, в свою очередь, может брать размеры от любого родителя.
В итоге код будет выглядеть так:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Центрируем контент по вертикали</title>
<style type="text/css">
html, body {height:100%; margin:0; padding:0;}
#table_div {
display:table;
height:100%;
width:100%;
}
#valgin_div {
display:table-cell;
height:100%;
width:100%;
vertical-align:middle;
}
#content {
padding:20px;
text-align:center;
background:#CCC;
position:relative}
</style>
<!--[if lte IE 7]>
<style type="text/css">
#valgin {display:block;}
#content {position:relative; top:50%; behavior:expression(function(t){var h = t.offsetHeight;if (t.h != h) {t.h = h;t.style.marginTop = -(h / 2 );}}(this));
}
</style>
<![endif]-->
</head>
<body>
<div id="table_div">
<div id="valgin_div">
<div id="content">
Я по-центру!
</div>
</div>
</div>
</body>
</html>
Теперь об особенностях display:table-cel:
- Он наследует от таблиц всё, включая задание размеров: блок перестаёт занимать всё пространство и формируется по объему содержимого, padding считается внутрь блок (не добавляется к width), а маржин – наружу (добавляется к width)
- Если вам нужно вставить в этот блок div с динамической(относительной) шириной и overflow – у вас ничего не выйдет. Как и в таблицах, блок не сможет рассчитать размер «выхода за пределы», скролл не появится и родителя растянет по содержимому. Если будет интересно, могу написать о некоторой хитрости, которая в большинстве случаев позволяет обойти это ограничение.
Но не всё так просто, как хотелось бы. IE ниже 8й версии не понимает этот атрибут, кто бы сомневался. На помощь к нам прийдут условные комментарии, behavior и expression. В условном комментарии [if lte IE 7] задаём родителю подходящий атрибут display (скорее всего block) а к блоку с содержимым применяем метод из самого начала: опускаем на 50% родителя и поднимаем на 50% собственной высоты. Вот тут нам и пригодится behavior и expression – для поднятия блока содержимого на 50% собственной высоты, заранее её не зная. Само выражение будет выглядеть так:
behavior:expression(function(t){var h = t.offsetHeight;if (t.h != h) {t.h = h;t.style.marginTop = -(h / 2 );}}(this));
Т.е. под стилями для всех браузеров (или в отдельном CSS) пишем следующее:
<!--[if lte IE 7]>
<style type="text/css">
#valgin {display:block;}
#content {position:relative; top:50%; behavior:expression(function(t){var h = t.offsetHeight;if (t.h != h) {t.h = h;t.style.marginTop = -(h / 2 );}}(this)); }
</style>
<![endif]-->
Вот, в общем-то и всё.
Страницу-пример можно посмотреть тут, и еще можете посмотреть на сайт где это всё использовалось тут.