Универсальное кросс-браузерное решение для резинового шаблона с двумя колонками

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

Добавить в закладки

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

15
Март
2008

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

  1. [...] добавлять отсупы, границы и бордюры. В статье “IE7/8 и общий случай двухколоночной резиновой вёрстки” я показывал, как получаются формулы для [...]

  2. андрей says:

    неплохая статья, но я вот столкнулся с проблемой реализации резинового двухколоночного макета (левая колонка фиксированная - правая тянеться) но при ентом футер должен быть прижатым вниз(у меня в принципе все вышло кроме ие6-если текста много проваливаеться через футер =(()…
    Может подскажеш как енто раелизовать? буду очень благодарен и послеюсь у тя на сайте =)))

    • Vladimir says:

      Андрей, а можно, пожалуйста, ссылку на то, что у Вас получилось?

      • Андрей says:

        Большое спасибо , что так быстро отозвался, проблему я уже решил(наверное просто поспал плохо =))) ).Вот что вышло:

        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;
        }

        • Андрей says:

          мде все-таки не все так и гладко :проблема заключаеться в том что када много текста контент блок 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;
          }

Подписаться на 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>

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

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