Кросс-браузерное решение для резинового макета с одинаковой высотой колонок и стопроцентной высотой
Недавно понадобилось сверстать резиновый трёхколоночный макет с высотой 100% и колонками одинаковой высоты. К моему удивлению, это оказалось не очень простым делом: вместо планируемого получаса это заняло намного больше времени.
Требования к макету:
- кросс-браузерность (куда без неё);
- минимальная высота: 100% (полное окно, независимо от высоты контента);
- минимум кода;
- все три колонки должны быть одинаковой высоты;
- никакого JavaScript.
Минимум кода означает минимум разметки:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Three Column Liquid Layout</title>
</head>
<body>
<div id="header">Header</div>
<div id="container">
<div id="content" class="column">
<p>Sed eleifend, sapien vel mollis euismod, sem velit semper ante...</p>
</div>
<div id="left" class="column">
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sollicitudin dolor nec nunc iaculis tincidunt...</p>
</div>
<div id="right" class="column">
<p>Phasellus sollicitudin. Fusce ut tellus. Vivamus dapibus. Cras eu elit. Vestibulum ante ipsum primis in faucibus orci luctus et...</p>
</div>
</div>
<div id="footer">Footer</div>
</body>
</html>
So far so good
, как любит говорить один мой коллега. Теперь переходим к разметке.
Начнём с общих определений:
background: #800000;
}
html, body {
margin: 0;
padding: 0;
border: 0;
}
body {
font: 14px/120% Verdana, Tahoma, Arial, Helvetica, sans-serif;
width: 90%;
margin: 0 auto;
}
Теперь переходим к 100% высоте. Помним, что Konqueror/KHTML имеет свою точку зрения по поводу того, кто задаёт скроллинг; также не забываем про IE6, который не понимает min-height
overflow: auto;
}
html:not(:nth-child(1)) {
overflow: visible; /* KHTML сам нарисует скроллинг, не будем ему мешать */
}
html, body {
margin: 0;
padding: 0;
border: 0;
width: 100%;
height: 100%;
}
#container {
height: auto !important;
height: 100%; /* для IE6 */
min-height: 100%;
}
* html #container { overflow: visible; }
Для IE6 мы должны задать overflow: visible, в противном случае контент будет нещадно обрезаться.
Задаем заголовок и подвал:
height: 3em;
background: red;
color: #FFF;
position: absolute;
top: 0;
width: 100%;
z-index: 1000;
left: 0;
}
.column {
padding-top: 3em !important; /* компенсация высоты заголовка */
}
#footer {
height: 3em;
color: #FFF;
background: green;
position: relative;
z-index: 1000;
margin-top: -3em;
width: 100%;
}
Заголовок позиционируем абсолютно, так как контейнер #container имеет как минимум стопроцентную высоту: задать высоту 100%-3em будет проблематично. Поэтому, считая, что высота заголовка нам известна (а так обычно всегда), мы просто помещаем заголовок "на территорию" контейнера, а высота заголовка будет компенсирована верхним отступом у колонок. Даже если нам придётся задать фоновый рисунок у #container, мы можем компенсировать высоту заголовка путём использования background-position.
Аналогично (только хуже
) с футером: его нужно поднять вверх на всю его высоту (отсюда относительное позиционирование и z-index) — как и в случае с заголовком, для поддержания стопроцентной высоты необходимо, чтобы он располагался "на территории" контейнера.
Теперь переходим к трём колонкам:
padding-left: 220px;
padding-right: 200px;
overflow: hidden;
float: left; /* IE 5.01 */
float/**/: none;
background: lime;
position: relative;
}
#left, #right, #content {
float: left;
position: relative;
padding-bottom: 1000em !important;
margin-bottom: -997em !important; /* компенсация высоты футера */
}
#left {
width: 220px;
background: url(images/tile-2.jpg) repeat;
margin-left: -100%;
right: 220px;
}
* html #left { /* У IE6 всё не как у людей */
left: 200px;
}
#right {
width: 200px;
background: url(images/tile-3.jpg) repeat;
margin-right: -100%;
}
#content {
width: 100%;
background: url(images/tile-1.jpg) repeat;
}
Теперь идут хаки. По слухам, в IE/Mac вышеприведённая техника для создания колонок одинаковой высоты не работает. Вернее, он работает, но страницу разносит по высоте (добавляется невидимый padding). Мне-то всё равно, но так как исправить просто (в смысле, сделать колонки разной высоты), то почему бы и нет:
float: left;
position: relative;
padding-bottom: 3em; /* компенсация высоты футера */
}
/* Прячем от IE/Mac \*/
#left, #right, #content {
padding-bottom: 1000em !important;
margin-bottom: -997em !important;
}
/**/
Переходим к Опере. Старые версии (7.0-7.2) не обрезают колонки по высоте. На помощь приходит EasyClearing:
content: 'EasyClearing';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
#container { display: inline-block; }
/*\*/
#container { display: block; }
/**/
Но, как это обычно бывает в жизни, исправил одну ошибку — вылезла другая: EasyClearing портит разметку в IE 5.01. По счастью, это легко лечится путём добавления float: left контейнеру #container:
float: left; /* IE 5.01 */
float/**/: none;
}
Тем не менее, мы исправили не все глюки в Опере. Для Opera 8, у которой есть свои глюки в обработке overflow: hidden, нам придётся убрать margin-bottom/padding-bottom с самих колонок и применить их элементу внутри колонок. Либо так:
#left, #right, #content {
margin-bottom: 0 !important;
padding-bottom: 3em !important; /* Компенсация высоты футера */
}
#left:before, #right:before, #content:before {
content: 'EasyClearing';
display: block;
background: inherit;
padding-top: 1000em !important;
margin-bottom: -1000em !important;
height: 0;
}
}


Насколько всё проще, если высота во всё окно не требуется:
margin: 0;
padding: 0;
border: 0;
width: 100%;
}
body {
font: 14px/120% Verdana, Tahoma, Arial, Helvetica, sans-serif;
position: relative;
min-width: 640px;
width: 90%;
margin: 0 auto;
}
#header {
height: 3em;
background: red;
color: #FFF;
width: 100%;
}
#container {
padding-left: 220px;
padding-right: 200px;
overflow: hidden;
float: left; /* IE 5.01 */
float/**/: none;
height: auto !important;
background: lime;
position: relative;
}
#left, #right, #content {
float: left;
position: relative;
}
/*\*/
#left, #right, #content {
padding-bottom: 32767px !important;
margin-bottom: -32767px !important;
}
/**/
@media all and (min-width: 0px) {
#left, #right, #content {
margin-bottom: 0 !important;
padding-bottom: 0 !important;
}
#left:before, #right:before, #content:before {
content: 'EasyClearing';
display: block;
background: inherit;
padding-top: 32767px !important;
margin-bottom: -32767px !important;
height: 0;
}
}
#container:after {
content: 'EasyClear';
display: block;
height: 0;
clear: both;
visibility: hidden;
}
#container { display: inline-block; }
/*\*/
#container { display: block; }
/**/
#left {
width: 220px;
background: cyan;
margin-left: -100%;
right: 220px;
}
* html #left {
left: 200px;
}
#right {
width: 200px;
background: yellow;
margin-right: -100%;
}
#content {
width: 100%;
background: #CCC;
}
#footer {
height: 3em;
color: #FFF;
background: green;
width: 100%;
}
В IE 7 не заработало
Футер вылазит на следующую страницу.
А так, магия! Дэвид Блейн отдыхает
Иван, работает всё в IE7
Скриншот приаттачен.
Если высота контента больше высоты окна, то футер вылезет на следующую страницу, так и задумывалось.
PS - Дэвид Блейн совсем не маг, то, что он вытворяет, может каждый… Непонятно, почему СМИ так это всё раздувают…
IE7_3cols_h100.png
Во-первых, спасибо за статью. Давно искал такую верстку. Сразу видно мастера.
Во-вторых, вопрос.
Можно ли усложнить задачу и вставить в этот дизайн горизонтальую навигационную панель, которая обычно визуально располагается под хедером? А в разметке желательно конечно, чтобы код был после контента.
Например так:
Header
Sed eleifend, sapien vel mollis euismod, sem velit semper ante...
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Duis sollicitudin dolor nec nunc iaculis tincidunt...
Phasellus sollicitudin. Fusce ut tellus. Vivamus dapibus. Cras eu elit. Vestibulum ante ipsum primis in faucibus orci luctus et...
Item 1
Item 2
Item 3
Footer
У меня не получилось позиционировать абсолютно, чтобы он был там где нужно.
В ИЕ 6.0.2 появляется горизонтальная полоса прокрутки.
.jpg
Arnoldovich, я пока в отпуске и посмотреть смогу только где-то в начале ноября. Но я бы тоже решал задачу через абсолютное позиционирование. Единственное, что навигационную панель пришлось бы размещать после #container.
К сожалению, валидатор выдает ошибки…
6: Unknown pseudo-element or pseudo-class :nth-child
6: Unknown pseudo-element or pseudo-class :not
67: Value Error : min-width Property min-width doesn’t exist in all but exists in all : 0
98: #left Value Error : background Too many values or values are not recognized : cyan
Валидировать нужно с профилем CSS 3, не 2
скажите, пожалуйста! Почему, если вставлять в левый блок ссылки так, чтоб при наведеннии на них они подчеркивались, этот левый блок уплывает вправо?
имелось ввиду в ие6