Кросс-браузерный резиновый трёхколоночный макет в высоту окна

Кросс-браузерное решение для резинового макета с одинаковой высотой колонок и стопроцентной высотой

Недавно понадобилось сверстать резиновый с высотой 100% и колонками одинаковой высоты. К моему удивлению, это оказалось не очень простым делом: вместо планируемого получаса это заняло намного больше времени.

Требования к макету:

  • кросс-браузерность (куда без неё);
  • минимальная высота: 100% (полное окно, независимо от высоты контента);
  • минимум кода;
  • все три колонки должны быть одинаковой высоты;
  • никакого JavaScript.

Минимум кода означает минимум разметки:

[-]
View Code HTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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, как любит говорить один мой коллега. Теперь переходим к разметке.

Начнём с общих определений:

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

[-]
View Code CSS
html {
    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, в противном случае контент будет нещадно обрезаться.

Задаем заголовок и подвал:

[-]
View Code CSS
#header {
    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) — как и в случае с заголовком, для поддержания стопроцентной высоты необходимо, чтобы он располагался "на территории" контейнера.

Теперь переходим к трём колонкам:

[-]
View Code CSS
#container {
    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). Мне-то всё равно, но так как исправить просто (в смысле, сделать колонки разной высоты), то почему бы и нет:

[-]
View Code CSS
#left, #right, #content {
    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:

[-]
View Code CSS
#container:after {
    content: 'EasyClearing';
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
}

#container { display: inline-block; }
/*\*/
#container { display: block; }
/**/

Но, как это обычно бывает в жизни, исправил одну ошибку — вылезла другая: EasyClearing портит разметку в IE 5.01. По счастью, это легко лечится путём добавления float: left контейнеру #container:

[-]
View Code CSS
#container {
    float: left; /* IE 5.01 */
    float/**/: none;
}

Тем не менее, мы исправили не все глюки в Опере. Для Opera 8, у которой есть свои глюки в обработке overflow: hidden, нам придётся убрать margin-bottom/padding-bottom с самих колонок и применить их элементу внутри колонок. Либо так:

[-]
View Code CSS
@media all and (min-width: 0px) {
    #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;
    }
}

Тестовая страница.

Автор: ; опубликовано в: CSS, HTML; метки: CSS, XHTML, кросс-браузерное решение, макет, резиновый макет, трёхколоночный макет
29
Июн
2008

RSS Комментарии к статье «Кросс-браузерный резиновый трёхколоночный макет в высоту окна» (36)  »

  1. saxarra

    БОЛЬШОЕ СПАСИБО!Хорошие комментарии и хороший макет.

  2. Руслан

    Макет действительно работает. Но, вот, решил я найти универсальный макет (для одной простенькой цмски), в котором можно было бы убрать, к примеру одну из боковых колонок и средняя растянулась бы на её место.
    В данном шаблоне сделать такой фокус простым убиранием div’а с боковой колонкой не прокатил…
    Как быть? Нужно ещё и в стилях что-то править? Но, они довольно тонко заточены всякими отступами да выступами… Даже страшно трогать :) ))
    А ещё эти боковые полосы – они действительно нужны?

  3. За шаблон действительно автору отдельное СПАСИБО.

    Но, есть в нем одна проблема.
    Если где-то в контенте установить якорь (ссылку вида <a>…), и перейти по этому якорю www.mysite/index.html#1, то весь контент, что над якорем заползает под header (короче исчезает).
    Виноваты в этом стили, с помощью которых как раз и получаются колонки во всю высоту:

    [-]
    View Code CSS
        padding-bottom: 1000em !important;
        margin-bottom: -997em !important; /* компенсация высоты футера */

    Вопрос к автору, каким еще способом в данном шаблоне лучше растянуть колонки на всю высоту?

    Что касается дела «Исчезающей колонки в IE6″ (или уползающей колонки), методом экспериментов было выяснено, что это все связано с использованием псевдоклассов hover и active с тегом a и стилем background (хоть и не сложная смесь, но осел ее осилить не смог). Если hover и active и стиль background применять к li, то IE6 их просто игнорирует и левая колонка не убегает.

    • Я в своё время искал решение, но не нашел — всё, что у меня получалось, это заставить код работать в одном IE, после чего всё напрочь ломалось в другом.

    • slavapth

      Если где-то в контенте установить якорь (ссылку вида <a>…), и перейти по этому якорю www.mysite/index.html#1

      Я тоже столкнулся с похожей проблемой – в FF. В др. браузерах (IE и Opera) такого не встречал. Долго рыскал в инете в поисках ответа. И решил воспользоваться методом «тыка». Ошибка в…

      Если убрать в стиле #container – overflow: hidden
      Но тогда появляется другая ошибка…ищу ответ дальше…

  4. Кирилл

    Спасибо за решение. Сам больше года пользовался другимм – много плюсов, но были и минусы.
    Вопрос, сосбственно, такой: можно ли как-то сделать так, чтобы футер не наезжал на бэкграунд колонок? У меня в футере прозрачный png, поэтому получается оч коряво.

    • Кирилл

      Ух как! Поигрался 5 минут, скрестил свое решение и ваше и получилось вообще чудесно. Кода раза в три меньше и удобнее :)
      Работает в последних лисе, опере и хроме, а также в ие 8, 7 и 6.
      Если есть желание выложить тут, могу скинуть на почту автору.

  5. Кирилл

    Отправил

  6. Людмила

    здравствуйте :)
    очень интересно узнать, что же за решение пришло от Кирилла… :)
    ==============================
    никак не могу найти способ, как сделать «резиновой» по высоте среднюю строку таблицы в 3 строки при фиксированной высоте верхней и нижней…

  7. Людмила

    спасибо большое автору этого блога, что готов делиться своими вариантами реализации не самых простых целей! :)
    =====================================================
    если кому-то нужно решение описанного мной выше вопроса,
    я его нашла здесь:
    http://krylov.org.ua/?p=682
    для меня, как для начинающего «вебера»,- самое простое решение без лишних телодвижений ))

  8. Plazmer

    А мне вот нужно сделать полупрозрачные колонки (с непрозрачным текстом) одинаковой высоты, и подвал, приклеенный к самому низу. В FF работает вот это:
    #left:before, #right:before, #content:before {
    content: 'EasyClearing';
    display: block;
    background: inherit;
    background-image:url("040_FFFFFF.png");
    padding-top: 1000em !important;
    margin-bottom: -1000em !important;
    height: 0;
    }

    040_FFFFFF.png – это белый полупрозрачный пиксель. В бэкграунд самого div’а ставить его бесполезно – будет двойное наложение из-за inherit. А если inherit убрать, то будет неполное заполнение колонок.
    Проблема в том, что не работает в IE. Вообще. Колонки прозрачные, пикселя нет, как-то по-другому он отрабатывает этот вот :before.

Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.

Оставить комментарий к записи «Кросс-браузерный резиновый трёхколоночный макет в высоту окна»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

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

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

गते गते पारगते पारसंगते बोधि स्वाहा