DIV-ные колонки одинаковой высоты на CSS

Дмитрий Сахань

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

Одна из таких — используя только обожаемую заказчиком DIV-ную вёрстку и вообще не привлекая JavaScript, дать колонкам сайта автоматическое выравнивание высоты по наиболее заполненной колонке, подобно тому как это происходило бы в нелюбимой табличной вёрстке.

Ниже предлагаю элементарное решение на основе всего двух объявлений в стилях сайта и одного обёрточного контейнера в теле страницы. Решение валидно для множества браузеров, кроме IE6-IE7, и при удалении одного свойства из стилей, привнесённых этим решением, может быть преобразовано под браузеры без поддержки CSS3.

Объяснение решения

Предположим, есть следующая разметка: шапка, три колонки (левая, центральная, правая) и подвал страницы.

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>Колонки</title>
 </head>
 <body>
  <div id="header"></div>

  <div id="left"></div>
  <div id="center"></div>
  <div id="right"></div>

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

Первым делом оборачиваем будущие колонки в DIV-контейнер. Например, назначим ему идентификатор columns.

<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="utf-8">
  <title>Колонки</title>
 </head>
 <body>
   <div id="header"></div>

   <div id="columns">
     <div id="left"></div>
     <div id="center"></div>
     <div id="right"></div>
   </div>

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

Осталось прописать в стили сайта следующее:

#columns {
    display: table;
    width: 100%;
    box-sizing: border-box;  /* не поддерживается в CSS2 */
    margin-left: 0;
    margin-right: 0;
}

#columns > div,
#columns > noindex > div {
    display: table-cell;
    vertical-align: top;
    width: auto;
    box-sizing: border-box;  /* не поддерживается в CSS2 */
}

Здесь мы указали браузеру, что требуем обёрточный контейнер показывать как блочную таблицу на всю ширину родителя, причём для исключения непредвиденных искажений размеры таблицы просим рассматривать по её границам (плюс неучитываемые margin-отступы с боков погашаем намеренно, иначе размер исказится). А вложенные в эту обёртку первородные DIV-ы призываем показывать как ячейки таблицы с подстраиваемой шириной (подстройку высоты браузер делает сам) и таким же рассмотрением размеров ячеек по их границам, а не по границам содержащегося в них контента.

В CSS2 не поддерживается свойство box-sizing, поэтому для старых браузеров, в случае необходимости указать размеры ячеек, делать это нужно за вычетом значений border- и padding-отступов.

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

#columns > #left,
#columns > noindex > #left {
    max-width: 300px;
    min-width: 300px;
    width: 300px;
}

#columns > #right,
#columns > noindex > #right {
    max-width: 200px;
    min-width: 200px;
    width: 200px;
    overflow: hidden;
}

Такое указание родства объектов, как использовано в продемонстрированном примере, необходимо для гарантии срабатывания стилевых правил лишь на конкретные колонки, принадлежащие непосредственно обёртке. А добавочное причисление случая с тегом noindex служит цели отработать ситуацию, когда СЕОшник сайта решил отдельную колонку закрыть от индексирования поисковыми серверами (нынче в строении интернет-магазинов это бывает принципиальной деталью).

Явные достоинства

  • простая реализация;
  • гарантированная одинаковая высота колонок;
  • колонки легко переставляются местами при необходимости;
  • легко добавить дополнительные колонки или изъять лишние;
  • колонки запросто скрываются от индексирования оборачиванием в тег noindex;
  • это не float-решение, поэтому отсутствует дефект «соскакивание колонки на новую строку».

Недостатки

  • не работает в браузерах IE6, IE7 — они изначально не поддерживают свойство display: table в стилях;
  • в браузере Safari 3.1 требуется удвоенная обёртка DIV-ами — здесь свойство display: table-cell дочернего объекта первого родства работает при наличии пары родительских контейнеров, вложенных один в другой со свойствами display: table и display: table-row;
  • нельзя использовать боковые margin-отступы у обёрточного DIV-а, если одновременно задаём ему ширину не в форме width: auto, потому что при рассмотрении размеров объекта браузер не принимает во внимание размеры margin-отступов, следовательно правый край объекта «уедет» дальше положенного на величину неучтённого отступа;
  • у колонок не получится задать margin-отступы, потому что браузер игнорирует всяческую манипуляцию такими отступами в объектах со свойством display: table-cell;
  • строго неподвижная фиксация ширины колонок вне зависимости от ширины их содержимого (то есть когда край колонки не сместится, даже если неразрывные части контента вылезут за край) сохраняется только при указании трёх ограничительных размеров (свойства width, min-width, max-width) в абсолютных единицах, в то время как использование относительного размера, скажем 20%, не гарантирует удержание ширины на неразрывной части контента, так как неявно позволяет браузеру автоподстройку ширины колонки в заём избыточного пространства соседних колонок с относительным или width: auto размером.

Не выкладывайте свой код напрямую в комментариях, он отображается некорректно. Воспользуйтесь сервисом cssdeck.com или jsfiddle.net, сохраните код и в комментариях дайте на него ссылку. Так и результат сразу увидят.