Кросс-браузерный семантически корректный резиновый макет с тремя колонками (сайдбары справа)

Очередной раз попав не туда, куда надо из Google, я натолкнулся на статью "Трехколоночный макет на CSS с одинаковой высотой колонок". Да, трехколоночные макеты (да еще и резиновые!) очень популярны, я смотрю :-) Но, несмотря на популярность таких макетов, многие верстальщики почему-то не хотят учиться и городят целый огород на div'ах.

В указанной статье приводится следующая разметка (я убрал пустые строки и изменил форматирование):

[-]
View Code HTML
<body>
    <div id="wrapper">
        <div id="header"></div>

        <div id="container">
            <div id="sub-container">
                <div id="wrpr">
                    <div id="content">
                        <div id="text"></div>
                    </div>
                    <div id="left"></div>
                </div>
            </div>
            <div id="right"></div>
        </div>

        <div id="footer"></div>
    </div>
</body>

Что мы видим: пример, как верстать не надо. Может быть, сказано слишком резко, но на мой взгляд, суп из div'ов (с глубиной вложенности 6) ничем не лучше табличной вёрстки (табличная вёрстка будет даже компактнее). Кроме того, большая часть этого супа не несёт семантической нагрузки. И вообще, при верстке нужно руководствоваться принципом KISS, но это моё сугубо личное мнение.

Попробуем переделать.
Начнём с разметки:

[-]
View Code HTML
<body>
    <div id="header"></div>

    <div id="container">
        <div id="content" class="column"></div>
        <div id="col1" class="column"></div>
        <div id="col2" class="column"></div>
    </div>

    <div id="footer"></div>
</body>

Как я уже отмечал в предыдущих статьях, названиям классов и атрибутам id нужно давать семантически значимые имена, но в качестве тестового примера пойдут и такие.

Простая разметка — простые стили:

[-]
View Code CSS
html, body {
    margin: 0;
    padding: 0;
    border: 0;
    width: 100%;
}

html { /* Для IE6 и IE7 */
    overflow: auto;
}

body {
    min-width: 50em; /* #container.paddingRight + #col1.offsetWidth + #col2.offsetWidth */
}

#container {
    overflow: hidden;
    padding-right: 25em; /* #col1.offsetWidth + #col2.offsetWidth */
    position: relative;
}

/*\*/
* html #container {
    height: 1%;
}
/**/

.column {
    position: relative;
    float: left;
    padding-bottom: 1002em !important;
    margin-bottom: -1000em !important;
    overflow: hidden;
}

#content {
    width: 100%;
}

#col1 {
    width: 10em;
    margin-right: -100%;
}

#col2 {
    width: 15em;
    margin-right: -100%;
    margin-left: 10em; /* #col1.offsetWidth */
}

#footer {
    clear: both;
}

Для краткости презентационные стили (aka расцветка) опущены.

Тестовая страница доступна здесь. Кстати, разметка получилась даже проще, чем здесь :-)

Но макет не был бы так хорош, если бы не позволял с лёгкостью добавлять отступы, границы и бордюры. В статье "IE7/8 и общий случай двухколоночной резиновой вёрстки" я показывал, как получаются формулы для вычисления значений границ и иже с ними (вспоминаем про эквивалентность преобразований), поэтому здесь приведу только конечный результат:

Элемент Свойство Формула
body min-width (#container.offsetWidth - #container.width) + (#content.offsetWidth - #content.width) + #col1.offsetWidth + #col2.offsetWidth
#container padding-right (#content.offsetWidth - #content.width) + #col1.offsetWidth + #col2.offsetWidth
#content margin-left =#container.paddingLeft
#col1 margin-left =#content.marginRight
#col2 margin-left #col1.offsetWidth + #col2.желаемый_marginLeft
#col1, #col2 margin-right -100%

В #container.paddingRight входит желаемый #col2.marginRight (но у Opera есть некоторые проблемы с его отображением).

Из-за того, что все колонки имеют равную высоту, отобразить border-bottom у них не представилось возможным.

Для IE8 добавляются следующие изменения:

  • #col1.marginLeft устанавливается в сумму горизонтальных отступов, границ и бордюров элемента #content;
  • #col2.marginLeft увеличивается на величину #col1.marginLeft.

Тестовая страница для экспериментов находится здесь.

[-]
View Code CSS
html, body {
    margin: 0;
    padding: 0;
    border: 0;
    font: 12px Verdana, Tahoma, Arial, Helvetica, sans-serif;
    width: 100%;
}

html {
    overflow: auto;
}

body {
    min-width: 81em; /* (38.5 + 0.5 + 2*1 + 2*1) + (2*1 + 2*1 + 0.5) + (10 + 2*1 + 2*1) + (15 + 0.5 + 2*1 + 2*1) = 43 + 4.5 + 14 + 19.5 = 57 + 24 */
}

#container {
    overflow: hidden;
    padding-right: 38.5em; /* (2*1 + 2*1 + 0.5) + (10 + 2*1 + 2*1) + (15 + 0.5 + 2*1 + 2*1) + желаемый margin-right для #col2 (0.5em) */
    position: relative;
    padding-left: .5em;
    padding-top: .5em;
    padding-bottom: .5em;
    margin: 1em;
    border: 1em solid black;
}

/*\*/
* html #container {
    height: 1%;
}
/**/

.column {
    position: relative;
    float: left;
    padding-bottom: 1002em !important; /* Фактически, padding-bottom = 2em */
    margin-bottom: -1000em !important;
    overflow: hidden;
}

#content {
    width: 100%;
    border: 1em solid green;
    padding: 1em;
    margin-right: .5em;
}

#col1 {
    width: 10em;
    margin-right: -100%;
    padding: 1em;
    border: 1em solid red;
}

*:first-child/**/+html #col1 {
    margin-left: 4.5em; /* #col1.paddingLeft + #col1.paddingRight + #col1.borderLeft + #col1.borderRight + #col2.желаемый_marginLeft */
}

#col2 {
    width: 15em;
    margin-right: -100%;
    margin-left: 14.5em; /* #col1.paddingLeft + #col1.paddingRight + #col1.borderLeft + #col1.borderRight + #col2.желаемый_marginLeft + #col1.width */
    padding: 1em;
    border: 1em solid blue;
}

*:first-child/**/+html #col2 {
    margin-left: 19em; /* #col2.marginLeft + #col1.marginLeft */
}

#footer {
    clear: both;
}
Добавить в закладки

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

22
Март
2008

Комментарии к статье «Резиновый трехколоночный макет с правосторонними сайдбарами» (17)  »

  1. Vladimir says:

    Дмитрий, по-моему, Вы где-то ошиблись… Я сохранил страницу себе на диск, добавил overflow: hidden .sidebar и всё отлично смотрится в Опере (по крайней мере, в 9.2x - 9.50 у меня нет).

    Тестовая страница: http://blog.sjinks.org.ua/test/imhoblog/test.html

  2. Dimox says:

    У меня как раз стоит Opera 9.5. И она, к сожалению, в данном случае overflow: hidden вообще не воспринимает, т.е. получается, что трабл только в Opera 9.5.

  3. Vladimir says:

    Дмитрий, тут такая проблема… Валидатор нашел 186 ошибок (!) и проблему с распознаванием UTF-8. Я бы всё же, наверное, попытался бы исправить ошибки, и только потом переходить к CSS. Валидатор жалуется на неправильно закрытые тэги.

  4. Vladimir says:

    Дмитрий, по ходу я прав - проблема в кривой разметке.

    http://blog.sjinks.org.ua/test/imhoblog/test.html

    Я убрал этот блок (из Подписки), и всё стало красиво:

    [-]
    View Code HTML
    <noindex>  
    <center>
    <br>
    <p>
    <!--  <a rel="nofollow" href="http://feeds.feedburner.com/imhoblog" rel="nofollow"><img src="http://imhoblog.ru/img/RSSicon32x32.png" height="32" width="32" style="border:0" alt="feedburner"/></a>  -->
    <a rel="nofollow" href="http://feeds.feedburner.com/imhoblog" rel="nofollow"><img src="http://imhoblog.ru/img/ratatfeed.gif" height="128" width="128" style="border:0" alt="Подпишись на RSS!" /></a>
    <br>
    <a rel="nofollow" href="http://feeds.feedburner.com/imhoblog" rel="nofollow"><img src="http://feeds.feedburner.com/~fc/imhoblog?bg=99CCFF&fg=444444&anim=0" height="26" width="88" style="border:0" alt="feedburner" /></a></p>
    <br>
    <a rel="nofollow" href='http://toodoo.ru/blog/19819/click' rel="nofollow">
    <img src='http://c.toodoo.ru/blog/19819/images/88x15w.gif' border='0' alt='количество читателей онлайн и всего' /></a>
    </a>
    <br>
    <!-- rss2email -->
    <a "nofollow" href="http://www.rss2email.ru?rss=http://feeds.feedburner.com/imhoblog" title="Получать RSS-ленту на почту" rel="nofollow"><img src="http://www.rss2email.ru/counter/typeA/23728_3.gif" border="0"></a>
    <!-- /rss2email -->
    <br>
    <a rel="nofollow" href="http://lenta.yandex.ru/settings.xml?name=feed&url=http://feeds.feedburner.com/imhoblog" rel="nofollow"><img src="http://lenta.yandex.ru/i/addfeed.gif" border="0" alt="Читать в Яндекс.Ленте" /></a>
    <br>
    <a rel="nofollow" href="http://fusion.google.com/add?source=atgs&feedurl=http%3A//feeds.feedburner.com/imhoblog" rel="nofollow"><img src="http://buttons.googlesyndication.com/fusion/add.gif" border="0" alt="Add to Google"></a>
    <br><br>
    <a href="http://imhoblog.ru/2008/05/09/chto-takoe-rss-chast-1-osnovy/" target="_blank" rel="nofollow">Что означает значок RSS?</a>
    <br>
    </center>
    <noindex>

    Для сравнения старая версия: http://blog.sjinks.org.ua/test/imhoblog/test2.html

    Мораль: ошибки в разметке надо исправлять :-)

  5. Dimox says:

    Ошибка с незакрытым тегом, слава Богу, не моя. Я подобных ошибок стараюсь не допускать.

    Удивительные вещи - после исправления этого тега футер возвращается на место, но отступ все равно остается, теперь уже под футером. Методом исключений определил, что отступ появляется сразу же после выполнения скрипта todoo-виджета (блок “Наши ИМХО люди”). Вот это побороть я уже не в силах.

  6. Vladimir says:

    Это из-за того, что WordPress по умолчанию оформляет все виджеты как списки, а этот TooDoo лепит внутрь элемента ul таблицу. Фикс - править исходный код плагина или попытаться поиграть с параметрами виджета $before и $after (если они есть).

Подписаться на RSS-ленту комментариев к статье «Резиновый трехколоночный макет с правосторонними сайдбарами» Trackback URL: http://blog.sjinks.org.ua/css/48-liquid-three-column-layout-with-right-sidebars/trackback/

Оставить комментарий к записи «Резиновый трехколоночный макет с правосторонними сайдбарами»

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

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

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