Универсальное кросс-браузерное решение для резинового шаблона с двумя колонками
В последнее время так называемая "резиновая вёрстка" (aka liquid layouts) становится всё более популярной, и далеко не последнюю роль в этом играет постоянное увеличение разрешения мониторов. Одним из часто применяемых шаблонов является двухколоночный (одна колонка имеет фиксированную ширину, другая является "резиновой"). Существует несколько разных подходов к вёрстке многоколоночных шаблонов, некоторые подходы приведены на A List Apart: Creating Liquid Layouts with Negative Margins и Multi-Column Layouts Climb Out of the Box. Второе решение, на мой взгляд, более элегантное; но как бы там ни было, оба решения являются, по сути дела, лишь частными случаями шаблона, когда колонки могут иметь свои границы, отступы и т.п. Конечно, расчет всех параметров не является особо сложным, но почему-то многие разработчики предпочитают не утруждать себя лишними вычислениями, а использовать вложенные div
, что не очень-то хорошо, ибо такие элементы не несут особой семантической нагрузки. А с появлением IE8 beta (которая альфа) расчеты усложнились, ибо IE8 довольно-таки криво считает координаты элемента с отрицательными границами. Поэтому мы попытаемся найти Универсальное кросс-браузерное решение для двухколоночного резинового шаблона.
Разметка (для простоты текст Lorem ipsum не приводится):
<div id="header"></div>
<div id="container" class="clearfix">
<div id="content" class="column"></div>
<div id="menu" class="column"></div>
</div>
<div id="footer"></div>
</body>
Презентационные стили:
font: 12px Verdana, Tahoma, Arial, Helvetica, sans-serif;
background: #CCC;
color: #000;
}
#header {
background: #D4E5FF;
font: italic normal 3em 'Times New Roman', Times, serif;
}
#footer {
background: blue;
height: 20px;
}
#container {
background: yellow;
}
Стили разметки:
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
html>body .clearfix {
display: block;
}
.clearfix {
display: inline-block;
}
/*\*/
* html .clearfix {
height: 1%;
}
/**/
.column {
position: relative;
float: left;
}
Зададим размеры элементов:
Элемент | width | padding | margin | border | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
top | right | bottom | left | top | right | bottom | left | top | right | bottom | left | ||
#header | auto | 1em | .3em | 1em | 1.818em | .5em | .5em | .5em | .5em | 1px | 1px | 1px | 1px |
#footer | auto | .5em | .5em | .5em | .5em | .5em | .5em | .5em | .5em | 1px | 1px | 1px | 1px |
#container | auto | 0em | 0em | 0em | 0em | .5em | .5em | .5em | .5em | 1em | 1em | 1em | 1em |
#menu | 25em | 0em | .5em | 0em | .5em | .5em | .5em | .5em | .5em | 1em | 1em | 1em | 1em |
#content | 100% | 2em | .5em | 10em | .5em | .5em | .5em | .5em | .5em | 1em | 1em | 1em | 1em |
Теперь выполним одно эквивалентное преобразование: перенесём внешние границы (margin
) с #content
и #menu
на #container
(соответственно, вместо margin
будет padding
):
Элемент | width | padding | margin | border | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
top | right | bottom | left | top | right | bottom | left | top | right | bottom | left | ||
#container | auto | .5em | .5em | .5em | .5em | .5em | .5em | .5em | .5em | 1em | 1em | 1em | 1em |
#menu | 25em | 0em | .5em | 0em | .5em | 0em | .5em | 0em | 0em | 1em | 1em | 1em | 1em |
#content | 100% | 2em | .5em | 10em | .5em | 0em | 0em | 0em | .5em | 1em | 1em | 1em | 1em |
Теперь увеличим padding-right
элемента #container
таким образом, чтобы при помощи отрицательного позиционирования можно было сместить элемент #menu
на территорию этого самого padding-right
. При этом должны учитываться margin
/border
/padding
элементов #menu
и #content
.
Получим следующие формулы:
Элемент | Свойство | Формула |
---|---|---|
#container | padding-bottom | min(желаемый #content.marginBottom, желаемый #menu.marginBottom) |
padding-top | min(желаемый #content.marginTop, желаемый #menu.marginTop) |
|
padding-left | желаемый #content.marginLeft |
|
padding-right | #menu.offsetWidth + желаемый #menu.marginRight + (#content.offsetWidth - #content.width) |
|
#menu | margin-right | -100% |
#content | margin-left | 0 |
margin-bottom | #menu.marginBottom - min(#menu.marginBottom, #content.marginBottom) |
В результате получим:
font: 12px Verdana, Tahoma, Arial, Helvetica, sans-serif;
background: #CCC;
color: #000;
}
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
html>body .clearfix {
display: block;
}
.clearfix {
display: inline-block;
}
/*\*/
* html .clearfix {
height: 1%;
}
/**/
#header {
background: #D4E5FF;
font: italic normal 3em 'Times New Roman', Times, serif;
margin: .5em;
padding: 1em .3em 1em 1.818em;
border: 1px solid blue;
}
#footer {
border: 1px solid red;
background: blue;
margin: .5em;
padding .5em;
height: 20px;
}
.column {
position: relative;
float: left;
}
#container {
padding-right: 37.5em; /* #menu.offsetWidth + #menu.desiredMarginRight + #content.offsetWidth - #content.width */
padding-left: .5em; /* desired #content.marginLeft */
padding-bottom: .5em; /* desired #content.marginBottom */
background: yellow;
border: 1em solid black;
margin: .5em;
}
#content {
width: 100%;
padding: 2em .5em 10em 5em;
border: 1em solid green;
margin: .5em .5em 0 0; /* margin-{left|bottom} is #container.padding{Left|Bottom} */
/* offsetWidth - width = (0.5 + 5) + (0.5) + (1 + 1) = 8em */
}
#menu {
width: 25em;
border: 1em solid red;
padding: 0 .5em 0 1em;
margin: .5em -100% .5em .5em;
/* offsetWidth = 25 + (0.5) + (0.5 + 1) + (1 + 1) = 29em */
}
Теперь, чтобы дизайн не бился при изменении размеров окна, добавим минимальную ширину элементу body (IE6 min-width
не понимает, но в IE6 и так всё прекрасно)
body.minWidth = (#container.offsetWidth - #container.width) + #menu.offsetWidth + (#content.offsetWidth - #content.width)
min-width: 78em;
}
У IE8 появилась интересная проблема, из-за которой #menu
смещается на недостаточное расстояние. Поэтому #menu
нужно подвинуть вручную на значение (#content.offsetWidth - #content.width)
:
margin-left: 8em; /* #content.borderLeft + #content.borderRight + #content.marginLeft + #content.paddingLeft + #content.paddingRight */
}
Для того, чтобы избежать проблем со скроллером в IE6, необходимо поставить overflow: auto
для html
. А в IE7 по неизвестным причинам body
слишком сильно расширяется и выходит за границы html
(горизонтально). В IE8 это поправили. Добавляем:
*:first-child+html body { overflow: hidden; }
*:first-child+/**/html body { overflow: visible; }
Результат здесь.
Скриншоты в различных браузерах здесь.
Есть один известный баг — в Опере не получается задать margin-right
для #menu
(который переносится в padding-right
#container
).
[...] добавлять отсупы, границы и бордюры. В статье “IE7/8 и общий случай двухколоночной резиновой вёрстки” я показывал, как получаются формулы для [...]
неплохая статья, но я вот столкнулся с проблемой реализации резинового двухколоночного макета (левая колонка фиксированная - правая тянеться) но при ентом футер должен быть прижатым вниз(у меня в принципе все вышло кроме ие6-если текста много проваливаеться через футер =(()…
Может подскажеш как енто раелизовать? буду очень благодарен и послеюсь у тя на сайте =)))
Андрей, а можно, пожалуйста, ссылку на то, что у Вас получилось?
Большое спасибо , что так быстро отозвался, проблему я уже решил(наверное просто поспал плохо =))) ).Вот что вышло:
header
left
center
footer
css:
html, body {margin:0;
padding:0;
width:100%;
height:100%;}
#header{
background-color:#333;
height:150px;
}
.wrap
{
position:relative;
min-height:100%;
height:auto !important;
height:100%;
color: #646464;
}
#left{
float:left;
width:200px;
background-color:#dc8;
}
#center {
margin-left:200px;
background-color:#eec;
}
#footer {
position:relative;
margin-top:-100px;
height:90px;
width:100%;
background:#646464;
}
мде все-таки не все так и гладко :проблема заключаеться в том что када много текста контент блок left пробивает футер , а с сенторм все окей.
css:
html, body {margin:0;
padding:0;
width:100%;
height:100%;}
#header{
background-color:#333;
height:150px;
}
.wrap
{
position:relative;
min-height:100%;
height:auto !important;
height:100%;
color: #646464;
}
#left{
float:left;
width:200px;
background-color:#dc8;
}
#center {
margin-left:200px;
background-color:#eec;
}
#footer {
position:relative;
margin-top:-100px;
height:90px;
width:100%;
background:#646464;
}