4 метода создания колонок одинаковой высоты
Оригинал: http://www.vanseodesign.com/css/equal-height-columns/
Перевод: Влад Мержевич
Одна из немногих вещей, которую не так просто сделать с помощью CSS — это создание колонок одинаковой высоты. Существуют разные подходы, у каждого из них есть свои плюсы и минусы, здесь я хочу показать четыре метода.
Задумаемся над тем, что мы подразумеваем под колонками одинаковой высоты. Как правило, мы не хотим, чтобы контент внутри каждой колонки был одинаковой высоты. Если бы это было так, тогда нет никакой проблемы, поскольку высота колонок, естественно, будет такой же. На деле под колонками одинаковой высоты мы имеем в виду колонки, которые выглядят одинаковыми без контента внутри.
Мы можем достичь этого добавляя фон позади колонок, чтобы они казались равной высоты. В результате получим фиктивную одинаковую высоту.
Желающие сразу смотреть демонстрацию и код могут щёлкнуть на любом изображении идущим перед каждым разделом ниже или обратиться к соответствующему демо.
Фиктивные колонки
Фиктивные колонки существуют уже долгое время. С 2004 года, если быть точным. За это время они были и, возможно, всё ещё остаются методом де-факто для создания колонок одинаковой высоты.
Этот простой трюк использует фоновое изображение которое повторяется по вертикали. Пример такого изображения показан ниже. Я увеличил высоту для наглядности.
Изображение обычно делается высотой в один пиксел, а его ширина совпадает с шириной макета. В том месте, где одна колонка переходит в другую, изображение для фиктивных колонок также должно меняться.
HTML
В этом примере мы будем использовать HTML, похожий на то, с чем мы уже работали, хотя я пропущу шапку и подвал, чтобы сосредоточиться на столбцах.
<div id="container">
<div id="sidebar">
<p>Боковая панель</p>
</div>
<div id="content">
<p>Основной контент</p>
</div>
</div>
Вы можете использовать в качестве контейнера body, но я предпочитаю применять контейнер div. Так вы сможете увидеть, что эта техника работает для создания колонок внутри общего макета, а не только самостоятельно.
CSS
#container {
width:960px;
margin:0 auto;
background: url("faux-columns.png") repeat-y;
overflow: hidden;
}
#sidebar {
float:left;
width:340px;
}
#content {
float:left;
width:620px;
}
CSS довольно прост. Настройка width и float для #sidebar и #content уже должны быть вам знакомы, также как настройка width и margin для #container. Новым здесь является добавление фонового изображения и применение overflow: hidden для контейнера. Нам нужно установить свойство overflow, чтобы контейнер div не схлопнулся и раскрыть обратно всё внутри плавающих элементов.
Контейнер будет той же высоты, что и самая высокая из колонок, а фоновое изображение создаёт эффект, словно короткая колонка имеет аналогичную высоту.
Данный метод лучше всего работает для макетов фиксированной ширины, но также подходит и для большинства резиновых макетов.
Вы также не ограничены простым изменением цвета фона. Границы, тени, узоры и др. могут быть добавлены в соответствующем месте фонового изображения. Для выбранных узоров следует создать изображение высотой больше одного пиксела.
Плюсы
- Легко настраивать.
- Работает независимо от того, какой столбец выше или ниже.
Минусы
- Необходима картинка которая создаёт дополнительный HTTP-запрос.
- Любое изменение макета требует переделки изображения.
- Нужно заранее знать, как будет выглядеть макет для создания изображения.
Псевдоколонки
Мне никогда не хотелось использовать фиктивные колонки. Не потому что это плохой метод, а потому что у меня есть пунктик — никогда не применять изображение для сплошной заливки цветом. Из-за этого я разработал собственный метод получения колонок одинаковой высоты, который за неимением лучшего термина буду называть псевдоколонки.
Он работает аналогично методу фиктивных колонок, который предполагает добавление фона к контейнеру. Это не общий подход к колонкам одинаковой высоты, поэтому он имеет ограниченную область применения, но если вы сталкиваетесь с таким случаем, всё это работает легко и просто.
HTML
Мы используем тот же HTML, что и в методе фиктивных колонок выше.
<div id="container">
<div id="sidebar">
<p>Боковая панель</p>
</div>
<div id="content">
<p>Основной контент</p>
</div>
</div>
CSS
CSS опять же весьма прост. Для разнообразия я выбрал резиновый макет, но вы можете легко всё настроить и для фиксированной ширины.
#container {
background: #555;
overflow: hidden
}
#content {
float:left;
width:75%;
background:#eee;
}
#sidebar {
float:left;
width:25%;
background:#555;
}
Кроме использования % вместо px заметьте, что я задал цвет фона для #content и #sidebar. Вам остается только установить его для любой колонки, которая будет выше, но здесь я специально задал цвет для двух колонок.
Основное изменение по сравнению с фиктивными колонками — вместо фонового изображения мы устанавливаем цвет фона. В принципе, это то же самое, что показывать цвет фона контейнера сквозь короткую колонку.
Ограничение следующее — мы заранее должны знать, какая колонка будет короче и в идеале эта колонка должна быть такой на всех страницах сайта. Звучит, как довольно серьёзное ограничение, но на практике, я считаю, одна из двух колонок обычно короче на большинстве, если не на всех, страницах. На тех страницах, где это не так, для исправления достаточно просто добавить больше или меньше контента.
Плюсы
- Просто настроить.
- Легко обслуживать.
Минусы
- Сложнее реализовать для трёх и более колонок.
- Требуется заранее знать высоту колонок.
- Не работает, когда колонки выше или короче на разных страницах.
Этот метод далёк от совершенства, но вы удивитесь, насколько часто он может применяться на практике.
Границы и отрицательные отступы
На этот метод я наткнулся не так давно на Smashing Magazine в статье Тьерри Кобленца, хотя позже нашёл статью Алана Пирса на A List Apart, написанную несколько лет назад об этом же методе. Используются границы и отрицательные отступы, чтобы создать видимость колонок равной высоты.
HTML
Ничего нового в HTML нет по сравнению с тем, что мы видели выше. В своей статье Тьерри применяет в качестве контейнера body, но я буду придерживаться использования контейнера div как делаю это обычно.
<div id="container">
<div id="sidebar">
<p>Боковая панель</p>
</div>
<div id="content">
<p>Основной контент</p>
</div>
</div>
CSS
В CSS начинается самое интересное. Контейнер просто используется для фиксации ширины и выравнивания макета по центру. Интересное происходит с #content и #sidebar.
#container {
width:960px;
margin: 0 auto;
}
#content {
float:left;
width:700px;
border-left: 260px solid #555;
}
#sidebar {
float: left;
width:260px;
margin-right: -260px;
position: relative;
}
Все фоновые цвета в этом методе устанавливаются для колонки #content. Мы задаём фон как обычно, а затем добавляем левую границу равную ширине боковой панели. Цвет границы совпадает с фоном боковой панели.
Если мы здесь остановимся, то вы увидите отображаемые колонки, однако наша левая граница выталкивает боковую панель прочь и мы должны вернуть её назад.
Вначале дадим боковой панели отрицательный правый margin равный её ширине (или ширине левой границы контента, они одинаковы). Это вернёт боковую панель туда, куда мы и хотим, но она по-прежнему не видна. Проблема в порядке наложения двух дивов. #content располагается поверх #sidebar, так что мы должны переместить #sidebar на передний план. Сделаем это путём добавления position: relative для боковой панели и теперь его содержание становится видно.
Плюсы
- Работает независимо от того, какая колонка выше или короче.
- Простая настройка, после того как вы понимаете, как это работает.
- Легко обслуживать.
Минусы
- Ширина боковой панели должна быть фиксирована, поскольку border-width понимает только абсолютные значения.
- Отрицательные margin потенциально могут привести к ошибке в некоторых старых версиях IE.
Рекомендую прочесть обе статьи, ссылки на которые я привёл выше, поскольку они предлагают более детальную информацию, чем я здесь. Обе статьи содержат код для использования этого метода с третьей колонкой, а статья Тьерри рассказывает о создании границ между колонками.
Смещение колонок и контейнера
Последний метод создал Мэтью Джеймс Тейлор. Из всех методов представленных здесь, на этот раз он будет работать в самых разных случаях использования.
Я оставил его на конец, так как метод немного сложный и вам, возможно, придётся прочитать несколько раз для понимания как он работает.
HTML
HTML похож на то, что мы видели выше, хотя вы заметите дополнительный контейнер div.
<div id="container-outer">
<div id="container-inner">
<div id="sidebar">
<p>Боковая панель</p>
</div>
<div id="content">
<p>Основной контент</p>
</div>
</div>
</div>
Как и в других методах, мы будем использовать эти контейнеры для установки фоновых цветов, которые появятся, словно они принадлежат нашим колонкам.
CSS
В CSS происходит несколько больше, чем мы видели до этого момента. Для #sidebar и #content задаётся float со значением left и устанавливается ширина, всё остальное помимо этого является новым.
Ключом этого метода выступает идея, что плавающий контейнер всегда имеет ту же высоту, что его содержимое. Размещая наши колонки внутри плавающих контейнеров, мы обеспечиваем, что контейнеры будут равны высоте самой длинной колонки.
#container-outer {
float:left;
overflow: hidden;
background: #eee;
}
#container-inner {
float:left;
background: #555;
position: relative;
right:75%;
}
#sidebar {
float: left;
width: 25%;
position: relative;
left: 75%;
}
#content {
float: left;
width: 75%;
position: relative;
left: 75%;
}
Первый шаг — добавить float к колонкам и контейнерам. Я применяю значение left, но направление в данном случае не важно. Используйте направление необходимое для вашего макета. Следующим шагом является установка фонов для двух контейнеров div. Я ставлю фон для #container-inner чтобы получить желаемое для боковой панели и фон для #container-outer чтобы получить желаемое для основного контента.
Если мы остановимся здесь, то увидим фон только для вложенного div, поскольку он по порядку наложения выше, чем внешний div.
Нам нужно немного позиционирования дабы сдвинуть внутренний div так, чтобы он показывался только там, где мы хотим отображать боковую панель. Это позволит фону у внешнего div проступать сквозь него там, где мы хотим показать колонку с контентом.
#container-inner {
position: relative;
right: 75%;
}
Позиционируем внутреннюю колонку и устанавливаем значение right на 75%, оно такое же, как ширина колонки с контентом.
Фоны на месте, но содержимое обоих колонок также сдвигается на 75% влево. Нам нужно сдвинуть их на место.
#sidebar {
position: relative;
left:75%;
}
#content {
position: relative;
left:75%;
}
Мы снова применяем относительное позиционирование и поскольку содержимое обоих колонок сместилось на 75% влево, нам надо сдвинуть это обратно на 75% вправо. Сделаем это установкой значения left в 75%. Теперь всё вернулось назад, где и должно быть.
Плюсы
- Работает независимо от того, какая колонка выше или короче.
- Работает с любым типом макета (фиксированным, резиновым, эластичным и др.).
- Можно сделать сколько угодно колонок.
Минусы
- Немного сложно для первого понимания.
- Требуются дополнительные несемантичные дивы.
В целом это наиболее надёжный метод и он гарантированно работает в любой ситуации. Я призываю вас поиграть с этим для настоящего понимания и прочитать статью Мэтью несколько раз.
В статье Мэтью идёт макет из трёх колонок и у него также есть демонстрация для четырёх и пяти колонок. Я решил показать макет из двух колонок в надежде что это сделает идею проще для понимания.
Дополнительные ресурсы
Это ни в коем случае не единственные методы создания колонок одинаковой высоты. Крис Койер некоторое время назад поделился несколькими другими методами на CSS Tricks, которые вы можете предпочесть представленным здесь.
Есть также много других методов, которые можно найти немного поискав. Думаю, что данная статья и статья Криса охватывает большинство из наиболее распространённых методов.
Резюме
Колонки одинаковой высоты являются желательной чертой дизайна, но их не всегда легко сделать с помощью CSS-макетов. В идеале мы должны были бы использовать что-то вроде height: 100% и на этом всё, но сейчас мы можем применять любой из методов, упомянутых выше.
Фиктивные колонки просты в настройке, но нужен дополнительный HTTP-запрос для изображения, а любое изменение макета требует новой картинки.
Псевдоколонки ещё проще, но имеют ограниченное применение для случаев, когда относительная высота обоих колонок известна и постоянна на страницах.
Границы и отрицательные отступы сравнительно просты в работе, не требуют предвидения о высоте колонок и прекрасно адаптируются к нескольким колонкам. Только нужно чтобы одна колонка была фиксированной ширины.
Смещение колонок и контейнера работает в большинстве случаев. Не нужно предварительно знать о высоте колонок и можно работать с любым желаемым числом колонок. Этот метод немного сложнее других.
Со временем я ожидаю более простого стандартного решения, но пока этих четырёх методов должно быть достаточно для вашего проекта.
Насколько часто вы делаете дизайн макета с колонками одинаковой высоты? Какой метод создания колонок вы при этом используете?