В последнее время так называемая "резиновая вёрстка" (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 не приводится):

[-]
View Code HTML
<body>
    <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>

Презентационные стили:

[-]
View Code CSS
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;
}

Стили разметки:

[-]
View Code CSS
.clearfix:after {
    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)

В результате получим:

[-]
View Code CSS
body {
    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)

[-]
View Code CSS
body {
    min-width: 78em;
}

У IE8 появилась интересная проблема, из-за которой #menu смещается на недостаточное расстояние. Поэтому #menu нужно подвинуть вручную на значение (#content.offsetWidth - #content.width):

[-]
View Code CSS
*:first-child+/**/html #menu {
    margin-left: 8em; /* #content.borderLeft + #content.borderRight + #content.marginLeft + #content.paddingLeft + #content.paddingRight */
}

Для того, чтобы избежать проблем со скроллером в IE6, необходимо поставить overflow: auto для html. А в IE7 по неизвестным причинам body слишком сильно расширяется и выходит за границы html (горизонтально). В IE8 это поправили. Добавляем:

[-]
View Code CSS
html { overflow: auto; }
*:first-child+html body { overflow: hidden; }
*:first-child+/**/html body { overflow: visible; }

Результат здесь.
Скриншоты в различных браузерах здесь.

Есть один известный баг — в Опере не получается задать margin-right для #menu (который переносится в padding-right #container).

Добавить в закладки
  • del.ici.ous
  • Digg
  • Furl
  • Google
  • Simpy
  • Spurl
  • Y! MyWeb
  • БобрДобр
  • Мистер Вонг
  • Yandex.Закладки
  • Текст 2.0
  • News2
  • AddScoop
  • RuSpace
  • RUmarkz
  • Memori
  • Google Bookmarks
  • Писали
  • СМИ 2
  • Моё Место
  • 100 Закладок
  • Ваау!
  • Technorati
  • RuCity
  • LinkStore
  • NewsLand
  • Lopas
  • Закладки - IN.UA
  • Connotea
  • Bibsonomy
  • Trucking Bookmarks
  • Communizm
  • UCA
  • Slashdot
  • Magnolia
  • Blogmarks
  • Current
  • Meneame
  • Oknotizie
  • Diigo
  • Funp
  • Hugg
  • Dealspl.us
  • N4G
  • Mister Wong
  • Faves
  • Yigg
  • Fresqui
  • Care2
  • Kirtsy
  • Sphinn

Связанные записи

15
Март
2008

Комментарии к статье «IE7/8 и общий случай двухколоночной резиновой вёрстки» (1)  »

Подписаться на RSS-ленту комментариев к статье «IE7/8 и общий случай двухколоночной резиновой вёрстки» Trackback URL: http://blog.sjinks.org.ua/css/31-ie-and-general-case-of-two-column-liquid-layouts/trackback/

Оставить комментарий к записи «IE7/8 и общий случай двухколоночной резиновой вёрстки»

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, Вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя