Колонки одинаковой высоты

Влад Мержевич

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

Таким образом, видно чёткое разделение подходов к вёрстке:

  • если используются слои, то колонки должны иметь высоту, которая определяется их содержимым;
  • колонки одинаковой высоты строятся с помощью таблицы.

Игнорирование этих принципов приводит к усложнению кода и появлению ошибок в отображении документа браузерами, как следствие, повышается время на разработку сайта и его отладку. Исключением может служить применение свойства height, которое устанавливает высоту слоёв. В примере 5.32 показано создание подобного макета.

Пример 5.32. Использование height

XHTML 1.0CSS 2.1IECrOpSaFx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Колонки одинаковой высоты</title>
  <style type="text/css">
   .layout { 
    overflow: hidden; /* Отмена обтекания */ 
   }
   .col1, .col2, .col3 { 
    width: 33.33%; /* Ширина колонок */
    float: left; /* Создаем колонки */ 
   }
   .layout div div {
    margin: 0 10px; /* Отступы */
    padding: 10px; /* Поля */
    height: 150px; /* Высота колонок */
    background: #4f703e; /* Цвет фона */ 
    color: #f5e8d0; /* Цвет текста */
    overflow: auto;
   } 
  </style>
 </head>
 <body>
  <div class="layout">
   <div class="col1">
    <div>
     <h2>SSI</h2>
     <p>Вставляет содержимое других файлов в код страницы.</p>
    </div>
   </div>
   <div class="col2">
    <div>
     <h2>Микроформаты</h2>
     <p>Формат и способ обмена данными между сайтами.</p>
    </div>
   </div>
   <div class="col3">
    <div>
     <h2>SVG</h2>
     <p>Язык разметки масштабируемой векторной графики для описания в 
     формате XML.</p>
    </div>
   </div>
  </div>
 </body>
</html>

Результат данного примера показан на рис. 5.23.

Колонки одинаковой высоты

Рис. 5.23. Колонки одинаковой высоты

Понятно, что объём текста в колонках может различаться, поэтому высоту через height обычно указывают с запасом. Ещё можно добавить свойство overflow со значением auto. Если текст превысит заданную высоту, появится полоса прокрутки.

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

Границы в качестве колонок

Суть метода в следующем — устанавливаем слева или справа от элемента границу, ширина которой совпадает с шириной одной из колонок. Понятно, что границы предназначены совсем для других целей, но в данном случае такое их использование позволяет получить желаемый результат. Для этого создаем слой с именем layout и для него устанавливаем стиль, как показано ниже.

.layout {
 border-left: 200px solid #c7e3e4; /* Ширина границы и цвет левой колонки */
 background: #e0d2c7; /* Цвет фона правой колонки */
}

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

.col1 {
 width: 200px; /* Ширина левой колонки */
 float: left; /* Превращаем в плавающий элемент */
 margin-left: -200px; /* Сдвигаем все влево на ширину границы */
}

В данном примере сочетание свойств float и margin-left позволяет расположить содержимое слоя прямо поверх границы. Для правой колонки col2 никаких дополнительных условий указывать не надо, текст будет располагаться как нам требуется.

Из-за того, что используется плавающий элемент, может получиться, что текст в левой колонке выходит за пределы цветного прямоугольника. Чтобы этого не произошло, следует отменить действие свойства float за счет использования clear. В данном случае использовать overflowhidden нельзя, будет обрезано пространство внутри границы, включая нашу фальшивую колонку. Окончательный код показан в примере 5.33.

Пример 5.33. Две колонки

XHTML 1.0CSS 2.1IECrOpSaFx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Две колонки одной высоты</title>
  <style type="text/css">
   .layout {
    border-left: 200px solid #c7e3e4; 
                 /* Ширина границы и цвет левой колонки */
    background: #e0d2c7; /* Цвет фона правой колонки */
   } 
   .col1 {
    width: 180px; /* Ширина левой колонки без полей */
    float: left; /* Превращаем в плавающий элемент */
    margin-left: -200px; /* Сдвигаем все влево на ширину границы */
   }
   .col1, .col2 { padding: 10px; }
   .clear { clear: both;  /* Отменяем обтекание */ }
  </style>
 </head>
 <body>
  <div class="layout">
   <div class="col1">Кумкват</div>
   <div class="col2">
    Небольшой экзотический фрукт оранжевого или оранжево-жёлтого цвета, 
    по виду напоминающий мелкий апельсин.
   </div><div class="clear"></div>
  </div>
 </body>
</html>

Результат примера показан на рис. 5.24.

Две колонки, созданные с помощью границы

Рис. 5.24. Две колонки, созданные с помощью границы

Для создания трёхколоночного макета границу следует добавить слева и справа от контейнера layout. Для разнообразия ширина правой колонки указывается в em (в процентах границу задавать нельзя).

.layout {
 border-left: 200px solid #c7e3e4; /* Ширина границы и цвет левой колонки */
 border-right: 15em solid #ecd5de; /* Ширина границы и цвет правой колонки */
 background: #e0d2c7; /* Цвет фона средней колонки */
}

Для первой колонки стилевой код остаётся неизменным, а третьей колонке следует указать свойство float со значением right и сдвинуть её вправо с помощью свойства margin-right (пример 5.34).

Пример 5.34. Три колонки

XHTML 1.0CSS 2.1IECrOpSaFx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Три колонки одной высоты</title>
  <style type="text/css">
   .layout {
    border-left: 200px solid #c7e3e4; 
    border-right: 15em solid #ecd5de; background: #e0d2c7;
   }
   .col1 { width: 180px; float: left; margin-left: -200px; }
   .col3 { width: 13em; float: right; margin-right: -15em; padding: 1em; }
   .col1, .col2 { padding: 10px; }
   .clear { clear: both; }
  </style>
 </head>
 <body>
  <div class="layout">
   <div class="col1">Грейпфрут</div>
   <div class="col3"><img src="images/grapefruit.jpg" alt="" /></div>
   <div class="col2">
    Грейпфрут — плод субтропического вечнозеленого дерева рода цитрусовых. 
    Диаметр в среднем составляет 10–15 см, кожура желтая, мякоть красного 
    оттенка. Вкус горький, чему способствует тонкая пленка вокруг каждой 
    дольки. Если ее убрать, то горечь сильно снизится.
   </div><div class="clear"></div>
  </div>
 </body>
</html>

Результат примера показан на рис. 5.25.

Три колонки, созданные с помощью границы

Рис. 5.25. Три колонки, созданные с помощью границы

Браузер IE6 содержит ошибку с границами и некорректно отображает данные примеры. Чтобы он правильно выводил макет, для него следует величину границ уменьшить вдвое.

<!--[if  IE 6]>
<style type="text/css">
 .col1 { margin-left: -100px; } 
 .col3 { margin-right: -7.5em; }
</style>
<![endif]-->

 Фоновая картинка

Принцип использования фонового изображения для колонок основан на том, что мы видим повторяющуюся по вертикали картинку, сверху которой располагается текст и другие элементы. Поскольку нам надо сделать эффект колонок, фон добавляется не к колонкам по отдельности, а для их родителя. Здесь имеет значение, какой это фон, что он собой представляет и каковы его размеры.  Предположим, что у нас двухколоночный фиксированный макет шириной 980 пикселов, левая колонка занимает ширину 200 пикселов. Создаём изображение размером 980х60 пикселов. Ширина соответствует ширине макета, а высоты обычно берётся 20–30 пикселов.

Многие разработчики делают рисунок высотой 1–2 пиксела, полагая, что объём файла будет минимальным, и загрузка произойдёт быстрее. Однако всё обстоит наоборот. Компьютер тратит в несколько раз больше времени для отображения одной страницы с узким фоном, что особенно заметно при прокрутке окна браузера. Так что при использовании фонового рисунка делайте изображение высотой не менее 20–30 пикселов — так отображение его на странице будет происходить быстрее.

Слишком скучно делать колонки однотонными, раз мы имеем дело с изображениями, поэтому добавим какие-нибудь ограничители по бокам колонок (рис. 5.26). Здесь самое главное, чтобы рисунок повторялся без стыков по вертикали.

Фоновый рисунок

Рис. 5.26. Фоновый рисунок

Теперь вставляем фон для слоя layout, внутри которого расположены наши колонки (пример 5.35).

Пример 5.35. Фон для фиксированного макета

XHTML 1.0CSS 2.1IECrOpSaFx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Двухколоночный фиксированный макет</title>
  <style type="text/css">
   .layout { 
    width: 980px; /* Ширина макета */ 
    background: url(images/2col.png) repeat-y; /* Фоновый рисунок */
    overflow: hidden; /* Отменяем обтекание */
   }
   .sidebar { width: 180px; float: left; padding: 10px; }
   .content { margin-left: 210px; padding: 10px; }
  </style>
 </head>
 <body>
  <div class="layout">
   <div class="sidebar">
    <ul>
     <li>Главная</li><li>Все коктейли</li><li>Коллекции</li>
     <li>Бокалы</li><li>Компоненты</li>
    </ul>
   </div>
   <div class="content">
    <h1>Яблочный эг-ног</h1>
    <p>Молоко — 40 мл, сок яблочный — 100 мл, сироп сахарный — 30 мм,
    один яичный желток.</p>
    <p>Приготовить напиток в миксере, подать в бокале хайбол 
    со льдом и соломинкой.</p>
   </div>
  </div>
 </body>
</html>

Результат данного примера показан на рис. 5.27. Хорошо заметно, что колонки имеют одинаковую высоту.

Колонки одинаковой высоты, созданные фоновой картинкой

Рис. 5.27. Колонки одинаковой высоты, созданные фоновой картинкой

При использовании в рисунке каких-либо декоративных элементов, следует позаботиться, чтобы текст от них был отодвинут через padding и не «налипал».

Для трёх и более колонок в фиксированном макете процесс подготовки изображения сходный, а вот для резинового макета есть ряд особенностей из-за того, что ширина макета может лежать в широком диапазоне. Тогда фоновую картинку необходимо сделать заведомо широкой, например, 2000 пикселов. Фон не влияет на ширину веб-страницы и если не помещается в отведённые ему размеры, то обрезается. Этим качеством и воспользуемся. В качестве примера рассмотрим резиновый макет с фиксированной правой колонкой шириной 300 пикселов. Для него сделаем изображение шириной 2000х30 пикселов с тёмно-красным прямоугольником справа (рис. 5.28).

Фон для резинового макета

Рис. 5.28. Фон для резинового макета

Фиксированная колонка располагается справа, поэтому фон также надо установить в правый верхний угол, указав 100% 0 для свойства background (пример 5.36).

Пример 5.36. Фон для резинового макета

XHTML 1.0CSS 2.1IECrOpSaFx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Двухколоночный резиновый макет</title>
  <style type="text/css">
   .layout { 
    background: url(images/bg-liquid.png) repeat-y 100% 0; 
                /* Фоновый рисунок */
    overflow: hidden; /* Отменяем обтекание */
   }
   .sidebar { width: 280px; float: right; padding: 10px; color: #fff; }
   .content { margin-right: 300px; padding: 10px; }
  </style>
 </head>
 <body>
  <div class="layout">
   <div class="sidebar">Колонка 2</div>
   <div class="content">Колонка 1</div>
  </div>
 </body>
</html>

Напоследок перечислю плюсы и минусы использования фона в качестве искусственных колонок.

Плюсы

  • Метод простой и не требует изменения существующего кода.
  • В рисунок можно добавить разные декоративные элементы вроде градиентов, линий и др. Это позволит разнообразить дизайн колонок.

Минусы

  • Наилучшие результаты получаются, когда одна из колонок или все имеют фиксированные размеры. Для макета, где ширина колонок резиновая, фон корректно добавить не получится.
  • При отключении изображений в браузере текст может оказаться нечитабельным. Впрочем, это легко обойти, задав наряду с фоновой картинкой цвет фона.
  • Файл с фоновой картинкой может иметь большой объём и долго загружаться. Отметим, что для простого изображения, вроде приведённого на рис. 5.27, это не так, при размерах 2000х30 пикселов файл занимает всего 275 байт.

Цвет фона

При имитации колонок одинаковой высоты с помощью фоновой картинки она добавляется через свойство background к родительскому элементу колонок (слой layer). Похожим образом работает и цвет фона. Его достаточно установить для слоя layer, а самой высокой колонке задать свой собственный цвет. В примере 5.37 приведён трёхколоночный макет, в котором цвет фона боковых колонок устанавливается через слой layer, а центральной колонки через слой col2.

Пример 5.37. Использования фонового цвета для колонок

XHTML 1.0CSS 2.1IECrOpSaFx

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Трёхколоночный резиновый макет</title>
  <style type="text/css">
   .layout { 
    background: #b2d235; /* Цвет фона крайних колонок */
    overflow: hidden; /* Отменяем обтекание */
   }
   .layout div{ float: left; }
   .col1 { width: 40%; }
   .col2 { background: #ffc60b; /* Цвет фона средней колонки */
    width: 20%; height: 200px; }
   .col3 { width: 40%; }
  </style>
 </head>
 <body>
  <div class="layout">
   <div class="col1">Колонка 1</div>
   <div class="col2">Колонка 2</div>
   <div class="col3">Колонка 3</div>
  </div>
 </body>
</html>

Свойство height в примере добавлено, чтобы стало заметно влияние цвета на колонках. В реальности оно не требуется.

У этого метода есть ряд недостатков, которые следует учитывать на практике.

  • Сложно оценить предварительно, какая из колонок будет иметь наибольшую высоту.
  • Для «раскрашивания» колонок применяется всего два цвета, так что нельзя задать трём и более колонкам разный цвет и чтобы они при этом имели одинаковую высоту.

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

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