Опубликовано автор в категориях Верстальщику.

Гениальное и простое решение предложил Matthew James Taylor в своей статье. Данное решение основано на чистом CSS без хаков, без применения картинок и Java-Script. В своей статье Мэтью сначала описывает саму проблему создания колонок с равной высотой, а потом предлагает само решение проблемы.

Проблема

Я не буду описывать полностью всю проблему создания блоков (div) одинаковой высоты в независимости от контента, думаю, что иллюстрация все прекрасно поясняет. Скажу лишь что основная проблема в том, что высота блока зависит от  контента в нем. К сожалению к div мы не можем применить heigh:100%;, либо фиксированная высота в пикселях, что очень нежелательно, либо зависимость от контента. В общем, на этом ограничим пояснение сути проблемы и перейдем к решению.

Решение

Первым шагом в решении проблемы создания колонок с равной высотой, станет их разделение на части. То есть каждую колонку мы разделим на отдельный блок чтобы решать проблему по частям. Плюс мы таким образом отделим контент от его оформления, фон отделим от самого контетна.

Плавающий контенер будет всегда той высоты, которую ему придает контент — печальная истина:( Единственным способ решить сделать div равным по высоте любой из существующих колонок с контентом — это «обернуть» в него данные колонки.

Как видите, в примере выше три блока заключены в один общи блок.

<div id="container1">
<div id="col1">Column 1</div>
<div id="col2">Column 2</div>
<div id="col3">Column 3</div>
</div>

А вот CSS для этой разметки

#container1 {
    float:left;
    width:100%;
}
#col1 {
    float:left;
    width:30%;
    background:red;
}
#col2 {
    float:left;
    width:40%;
    background:yellow;
}
#col3 {
    float:left;
    width:30%;
    background:green;
}

Суть данной разметки и CSS заключается в том, что все блоки, и те, которые с контентом, и тот, который их содержит должны быть плавающими (иметь свойство float, причем не важно в каком направлении). Если мы не придадим свойство float для всех контейнеров, то контейнер, содержащий в себе блоки с контентом не сможет охватить их, и в итоге высота общего конейнера на самом деле будет равна «0», а не высоте самого высокого блока с контентом. В конце статьи я предложу решение этой проблемы.

Добавление дополнительных вложенных контейнеров

Далее нам следует добавить еще несколько контейнеров в основной контейнер, который содержит в себе блоки с контентом. В итоге, мы должны получить равное количеству блоков с контентом, количество «оберток». В нашем случае на нужно добавить еще два вложенных контейнера. А далее мы должны убрать свойство background у блоков с контентом и «передать» его «контейнерам-оберткам».

А так выглядит разметка этого примера:

<div id="container3">
    <div id="container2">
        <div id="container1">
            <div id="col1">Column 1</div>
            <div id="col2">Column 2</div>
            <div id="col3">Column 3</div>
        </div>
    </div>
</div>

А вот CSS, обратите внимание, что все контейнеры имеют свойство float, а «контейнеры-обертки» имеют ширину 100%. При этом фон имеют только «обертки»:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#container3 {
    float:left;
    width:100%;
    background:green;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
}
#container1 {
    float:left;
    width:100%;
    background:red;
}
#col1 {
    float:left;
    width:30%;
}
#col2 {
    float:left;
    width:40%;
}
#col3 {
    float:left;
    width:30%;
}

Сдвигаем контейнеры с помощью относительного позиционирования

Используя относительное позиционирование мы передвинем контейнеры на их новое место. При правильном позиционировании «контейнера-обертки» становится виден лежащий под ним слой, что и создает иллюзию равной высота колонок. DIV с #container2 мы смещаем на 30% влево относительно содержащего его блока, и обнажаем зеленый фон #container3. А DIV с #container1 мы сдвигает на 40% влево относительно содержащего его блока #container2 и обнажаем желтый фон последнего для центральной колонки. Соответственно красная секция остается видимой всего на 30% и формирует красный фон ля третьей колонки.

А вот CSS, в котором описаны указанные выше процедуры:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#container3 {
    float:left;
    width:100%;
    background:green;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:30%;
}
#col2 {
    float:left;
    width:40%;
}
#col3 {
    float:left;
    width:30%;
}

Возвращаем колонки с контентом на свои позиции

Теперь нам нужно вернуть на место колонки с контентом, которые сместились вместе с содержащим их контейнером. Для этого мы снова применяем относительное позиционирование.

И последнее, что нам нужно сделать — это «обрезать» все, что выступает за пределы видимой области, назначив overflow:hidden; самому первому «контейнеру-обертке». В нашем случаее это #container3.

Смотрим CSS приведённых выше операций:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#container3 {
    float:left;
    width:100%;
    background:green;
    overflow:hidden;
    position:relative;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:30%;
    position:relative;
    left:70%;
}
#col2 {
    float:left;
    width:40%;
    position:relative;
    left:70%;
}
#col3 {
    float:left;
    width:30%;
    position:relative;
    left:70%;
}

Казалось бы все, но для полной красоты нам не хватает отступов в колонках с контентом. Сейчас мы их сделаем. Но если мы добавим просто отступы с помощью padding, то наша разметка потеряет кроссбраузерность, за счет известного бага Internet Explorer с подсчетом ширины колонок. Итак, чтобы сделать отступы кроссбраузерными нам нужно применить следующий трюк.

Для того чтобы создать видимость отступов мы просто сделаем наши колонки уже, с учетом величины отступов слева и справа, а потом сдвинем их на нужное число с помощью отностиельного позиционирования. В нашем случае мы возьмем величину отступа в 2% и поэтому колонка шириной 30% будет иметь ширину 26%, а колонка шириной 40% будет иметь ширину 36%. Но теперь, когда мы будем возвращать колонки на место с помощью поиционирования, нам нужно помнить, что они стали уже и, соответственно, увеличить процент смещения для кажой колонки. в нашем случае для первой на 2%, а для остальных к смещению предыдущей добавляем еще 4%.

Конечный CSS

В результирующем CSS нам еще нужно добавить для каждой колонки с контентом свойство overfloww:hidden;, для того, чтобы в случаее, если содержимое превысит допустимую ширину, например картинка слишком широка, наша разметка не развалилась. Это сделано для IE, посокльку другие браузеры удержут разметку даже в таком случае.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#container3 {
    float:left;
    width:100%;
    background:green;
    overflow:hidden;
    position:relative;
}
#container2 {
    float:left;
    width:100%;
    background:yellow;
    position:relative;
    right:30%;
}
#container1 {
    float:left;
    width:100%;
    background:red;
    position:relative;
    right:40%;
}
#col1 {
    float:left;
    width:26%;
    position:relative;
    left:72%;
    overflow:hidden;
}
#col2 {
    float:left;
    width:36%;
    position:relative;
    left:76%;
    overflow:hidden;
}
#col3 {
    float:left;
    width:26%;
    position:relative;
    left:80%;
    overflow:hidden;
}

Вот и все. Лично мне очень понравился предложенный Метью метод. На демонстрацию его в действии можно взглянуть на демо-страничке автора: 2 колонки, 3 колонки, 4 колонки и 5 колонок.

От себя добавлю, что можно избежать проблемы высоты плавающий «контейнеров-оберток», если использовать фикс высоты плавающих блоков, который нормально воспринимается валидатором CSS и работает во всех браузерах. Для этого «оберткам» можно добавить class=»clearfix», а в CSS добавить такой код:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* *** Float containers fix *** */
.clearfix:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
 
.clearfix{display: inline-block;}
 
/* Hides from IE-mac \*/
* html .clearfix{height: 1%;}
.clearfix{display: block;}
/* End hide from IE-mac */

Теперь точно все. Удачной вам верстки!
P.S.
Для тех кому надоела верстка и захотелось экзотики есть недвижимость в Черногории — виллы, дома, квартиры. У кого на что хватит?
А если вы вдруг затеяли социальный проект, то вам обязательно понадобиться наружная социальная реклама

37 комментариев к записи “Кросс-браузерное CSS-решение создания колонок с равной высотой”

  1. Zodios

    Спасибо за обзор, было познавательно прочитать.

    З.Ы. Мне кажется стоит увеличить у текста line-height и letter-spacing(можно задавать дробные величины 0.1-X) тогда текст будет более читабельным, а то тяжело перепрыгивать с строчки на строчку и в слове «clearfix» в тексте буквы c и l сливаются эмитируя букву d

    Ответить
  2. Hiway

    Спасибо за совет. Честно говоря давно думаю над тем, чтобы полностью сменить диз. Даже уже рисовать начал. Но руки как всегда доходят до этого в последнюю очередь. Вот и выходит парадокс — пишу о том, как надо, а сам делаю как не надо…

    Ответить
  3. Иван

    В IE6 делаю четыре колонки внутри дива фиксированной ширины отцентрованном по горизонтали.
    В результате див «уезжает» влево.

    Ответить
  4. batch2k

    «Это сделано для IE, посокльку другие браузеры удержут разметку даже в таком случае.»

    А есть ли способ и для IE не включать оверфлоу? У меня в левой колонке стоит меню, которое раскрывается на разных страницах в иерархическом режиме (списки), и поэтому в некоторых случаях его ширина оказывается довольно большой.
    Результат в других браузерах меня устраивает (в основном блоке во вложенном диве есть левое поле, так что «заехавшее» меню выглядит пристойно), а вот в IE6 косяк… Блоки начинают уезжать.

    Ответить
  5. Hiway

    “Это сделано для IE, поскольку другие браузеры удержут разметку даже в таком случае.
    А есть ли способ и для IE не включать оверфлоу?”
    — owerflow можно не использовать в том случае, если ты уверен, что в твоем контенте в левой колонке не будет объектов шире, чем ширина колонки. А если это не подходит, тогда можно использовать решения на основе скриптов, посмотри, тоже писал об этом в блоге.

    Ответить
  6. batch2k

    А если это не подходит, тогда можно использовать решения на основе скриптов, посмотри, тоже писал об этом в блоге.
    Признайтесь — только честно, без семантического лицемерия! — что в описанном мной случае (когда нет гарантии, что содержимое влезет в колонку целиком), таблицы ИДЕАЛЬНО подходят для вёрстки, а ДИВы будут использовать только из болезненного самолюбия.
    Ведь так?

    Ответить
  7. Hiway

    Признайтесь — только честно, без семантического лицемерия! — что в описанном мной случае (когда нет гарантии, что содержимое влезет в колонку целиком), таблицы ИДЕАЛЬНО подходят для вёрстки, а ДИВы будут использовать только из болезненного самолюбия.
    Ведь так?
    Нет, в описанном вами случае, все вполне реализуемо блочной версткой, при этом, вот http://www.master-web.info/equal-height-css-columns/ здесь сказано как. А если вы не можете прикрутить к своей верстке либо это, либо одно из решений в статье по ссылке выше, то вам нужно было заниматься версткой 10 лет назад, а сейчас просто не ваше время. Без обид.

    Ответить
  8. batch2k

    Мне кажется, Вы неправильно меня поняли. «Прикрутить» можно что угодно, да только вот это обозначает, что к дивам, которые, вообще-то не впились никому как таковые (мне, во всяком случае), приходится скотчиком приматывать то, что является неотъемлемой частью таблиц. Ну зачем отрицать очевидное? (Не зря же в некоторых версиях стандартов есть эмуляция таблиц с помощью дивов?)
    Другое дело, если Вы принципиально не хотите использовать таблиц при вёрстке, — тогда да. Тогда и скрипты пойдут в ход, и фальшивый фон колонок.
    Мне кажется, что в некоторых случаях (не во всех, конечно) использование только дивов — это ничем не оправданная и, в общем-то, бесполезная принципиальность. Без обид.

    Ответить
  9. Ника

    А что если сделать 5 колонок? Как тогда? У меня например проблема с изображениями. Есть резиновая верстка, и нужно добавить 5 изображений равно удаленных друг от друга. Причем, левое изображение уже прижато к левому краю монитора, а вот с правым, самым последним изображением, ерунда получается. Буду признательна за помощь 🙂

    Ответить
  10. hiway

    @Ника: По пунктам.
    1. Что касается пяти колонок. То есть же схема в картинках, как располагаются слоя. Соответственно высчитываем маргины, добавляем два псевдослоя — получаем результат.
    2. Что касается ваших картинок, то здесь нужно более четкое описание проблемы.

    Ответить
  11. vladgor

    hiway ,добрый день!Подскажите, в чём может быть проблема, когда левая колонка(позиция left шаблона Joomla 1,5) в IE6 меняет цвет с бежевого(как в плавающей картинке-«подкладке») на голубой, хотя в других броузерах всё смотрится нормально.Этот эффект появляется, когда присутствуют обе колонки — правая и левая,если по одной — всё нормально. Буду признателен за помощь

    Ответить
  12. Hiway

    @vladgor: Смотри, ситуация здесь такая, что нужно знать, что за шаблон, смотреть проект, страницу с ошибкой. Просто того, что ты изложил в вопросе недостаточно, вернее ответить на него невозможно в силу отсутствия перечисленных выше деталей.

    Ответить
  13. vladgor

    Виктор, ситуация следующая: шаблон был взят из приложения к книге Barrie North «Практическое руководство по Joomla!» — назывался csstemplatetutorialstep4(могу его перебросить, если скажете адрес). Он сделан на CSS, адаптируется под разное разрешение монитора и всё б ничего — но когда активны обе колонки — то в любимом IE6 левая колонка меняет цвет фона,аналогичный цвету поля ввода комментария на голубой(откуда берётся — мне сложно сказать, ещё нет того опыта).Фон в колонках задаётся при помощи «скользящих» изображений, для каждой своё(левая — 20% цвет+80% белый фон, правая — 80% прозрачная+20% цвет). В момент обновления страницы в IE6 мелькает правильный фон, а затем голубой на левой колонке остаётся.Вот , в общем и всё.Страницы с ошибкой нет — просто она выглядит не так , как в Опере или Мозиле. Такая вот проблема.

    Ответить
  14. vladgor

    Проблема решена — она заключалась в большом объеме одной из картинок(как ни странно!) Благодарю за уделённое внимание

    Ответить
  15. hiway

    @vladgor: Спасибо, конечно, но благодарить не за что. Ссори, что не удели должного внимания. Вернее не успел:)

    Ответить
  16. vladgor

    Сайт у Вас весьма интересный — и судя по инфо о себе с темой Joomla! разобрались самостоятельно. Я тоже поставил перед собой такую цель — если порекомендуете, как этого проще достичь -буду признателен.

    Ответить
  17. hiway

    @vladgor: Тут рекомендация только одна — лучший способ обучения — это практика. Чем больше нестандартных и сложных задач перед вами возникает в процессе работы, тем лучше и глубже вы вникнете в систему, чтобы их решить. А что касается «пищи для ума», то думаю лучше всего читать доки на joomla.org и смотреть форум там же.

    Ответить
  18. Богдан

    Скажите, а как сделать, чтобы эти три колонки были с скругленными углами с помощью картинок?

    Ответить
  19. hiway

    @Богдан: Способов создания закругленных углов есть очень много. При этом можно эт сделать как картинками так и нет. Но если говорить о данной конкретной ситуации придать колонкам скроенные углы без всяких изощрений можно лишь в том случаи, если у вас фиксированная ширина сайта. В случае же с резиновой шириной — это проблематично и здесь, пожалуй, стоит прибегнуть к JS решениям.

    Ответить
  20. Богдан

    Спасибо за быстрый ответ. Да, я ищу универсальное решение. То есть хочу для себя сделать макет, который бы соответствовал таким условиям:
    1. ширина резиновая, например 90%
    2. левая и правая колонка фиксированной ширины
    3. в разметке чтобы сначала шел основной контент, потом левая колонка, а потом правая
    4. колонки одинаковой высоты
    5. колонки с закругленными углами с помощью картинок
    6. Футер всегда внизу экрана
    Возможно ли создать такой шаблон, чтобы удовлетворял хотя-бы первые пять пунктов. Спасибо

    Ответить
  21. constantant

    Здрасте, уважаемые.
    Ищу подобное решение, но только мне надо чтоб колонки по краям были фиксированной ширины… честно говоря, я что-то не понимаю как из вышеприведённого примера сделать то что мне надо.
    А вообще на javaScript-ом это делать куда приятнее, и не надо говорить: «а если яваскрипт отключен?» — это бред, ну давайте верстать для ZX Spectrum или БК01-10 ещё)))

    Ответить
  22. mctraf

    Я выравнивание высоты колонок решал и буду решать таблицами пока не сделают нормальное css решение и его поддержку во всех браузерах. И пусть орут что хотят, яблоко им в рот.

    Ответить
  23. HOG_Seruj

    Подскажите пожалуйста, а как быть в такой ситуации:
    правый и левый блок очень длинные и нужно что бы высота правого была равна центральному блоку и высота левого = центральному, а в правом и левом блоке полоса прокрутки.

    Ответить
  24. pfo.Agency

    .wrp{
    display:block!important;
    width:100%!important;
    float:left!important;
    margin:0!important;
    padding:0!important;
    }
    .c{
    margin:0 300px;
    background:#0f0;
    }
    .l{
    float:left;
    width:300px;
    margin:0 0 0 -100%;
    background:#ff0;
    }
    .r{
    float:left;
    width:300px;
    margin:0 0 0 -300px;
    background:#0ff;
    }

    центр

    леволеволеволево
    право

    jQuery(function($){

    var toAlign = function(){
    var maxHeight = 0;
    $(‘.col’).removeAttr(‘style’).each(function(i, dom){
    if($(dom).height() > maxHeight ){
    maxHeight = $(dom).height();
    }
    });
    return $(‘.col’).height(maxHeight);
    };
    return toAlign();
    });

    просто и быстро 🙂

    Ответить
  25. pfo.Agency

    .wrp{
    display:block!important;
    width:100%!important;
    float:left!important;
    margin:0!important;
    padding:0!important;
    }
    .c{
    margin:0 300px;
    background:#0f0;
    }
    .l{
    float:left;
    width:300px;
    margin:0 0 0 -100%;
    background:#ff0;
    }
    .r{
    float:left;
    width:300px;
    margin:0 0 0 -300px;
    background:#0ff;
    }

    центр

    леволеволеволево
    право

    jQuery(function($){

    var toAlign = function(){
    var maxHeight = 0;
    $('.col').removeAttr('style').each(function(i, dom){
    if($(dom).height() > maxHeight ){
    maxHeight = $(dom).height();
    }
    });
    return $('.col').height(maxHeight);
    };
    return toAlign();
    });

    просто и быстро 🙂

    Ответить
  26. ombrax

    Спасибо за урок. Действительно, оригинально. Но вот вопрос, если потребуется сделать такой блок из трех колонок по центру, с тенью и закругленными углами, тогда как?

    Ответить
  27. Alex

    Очень полезная статья. Решил взять на вооружение. Только немного изменить размеры. Но с математикой что-то не получается… Мне нужно, чтобы все эти три колонки в сумме составляли по ширине 1000 пикселей и отображались по центру окна браузера. Подскажите, пожалуйста, какими будут цифры в css, если я весь этот Ваш код запихиваю в ещё один центрированный по горизонтали относительно body основной контейнер div id=»main» шириной в 1000px, а правая и левая колонки должны быть по 200px (20%) каждая, центральная — 600px (60%), отступы, допустим, по 10px (1%). Что-то не могу сообразить, как подсчитать цифры в css… Помогите, пожалуйста)))

    Ответить
  28. Alex

    Извините за беспокойство, я ещё раз внимательно прочитал статью, сообразил что к чему — и всё получилось)))))) Один только вопрос: это кроссбраузерное решение? Где-то я слышал, что Opera не понимает overflow:hidden…

    Ответить

Оставить комментарий

  • (не будет показан)