Многоколоночная компоновка. «Вылазим из блоков».
16:03 21 Дек. 2007 Автор: Кирилл ХарченкоМы все знакомы с проблемами, возникающими при попытках построения многоколоночного макета с колонками равной высоты. О них было достаточно написано ранее, так что не будем вдаваться в подробности.
Для проекта, над которым я недавно работал, требовался растягивающийся макет с двумя колонками разной высоты. Как обычно, какая из колонок будет длиннее заранее неизвестно. Сразу же возникла мысль о методе ложных
колонок Дэна Цедерхолма, но мне нужна была разметка с изменяющейся шириной колонки. Также я рассматривал и метод описанный в статье Один вывереный макет
, но он показался мне ненадежным и требующим слишком много лишнего кода и хаков. Я даже задумался об использовании JavaScript для надежности, но все таки почувствовал, что так просто нельзя… В отчаянии я уже был готов (о боже!) верстать все в таблице.
Но какой-то выход должен был быть. Мне просто нужно было подумать как-то иначе, нестандартно, неблочно
. А что у нас находится за пределами блока? Его рамка. Если поместить боковой блок (rail
) поверх границы (border) основного блока с контентом, можно сымитировать две колонки одинаковой высоты независимо от того, какая из них больше.
Вам такой метод наверняка покажется знакомым, подобный метод ранее был предложен Дугласом Ливингстоном и дополнен Холли и Джоном Бергевином из Position Is Everything. Представленный ниже метод основывается на той же идее, но позволяет обходиться меньшей степенью вложенности элементов, допускает большое количество вариаций и в общем превосходит по количеству достоинств методы, основанные на Одном вывереном макете
. Вот как это делается:
HTML:
<div id="container"> <div id="content">Это некий<br />контент</div> <div id="rail">Это текст сбоку</div> </div>
CSS:
#container{
background-color:#0ff;
overflow:hidden;
width:750px;
}
#content{
background-color:#0ff;
width:600px;
border-right:150px solid #f00; /* Ширина и цвет бокового блока */
margin-right:-150px; /* Поклон Райану Бриллу */
float:left;
}
#rail{
background-color:#f00;
width:150px;
float:left;
}
Делаем границу основного блока с контентом такой же ширины и цвета, что у бокового блока, а затем задаем боковому блоку обтекание (float). Свойство margin-right:-150px блока с контентом позволяет боковому блоку точно разместиться в нужном месте. Если блок с контентом больше бокового, граница блока с контентом увеличивается вместе с ним, создавая иллюзию, будто бы боковой блок увеличивает свою высоту вместе с основным блоком. Цвет фона блока-контейнера совпадает с цветом фона основного блока, так что если больше боковой блок (rail
), то высота блока-контейнера растет вместе с ним, создавая впечатление будто растет блок с контентом. Остается внести в CSS небольшие изменения, чтобы расположить боковой блок (rail
) слева, вне зависимости от того, больше ли 2colfixedleftcontenttallest.htmlблок с контентом (content
) или боковой (rail
).
Посмотрите на этот метод в действии или взгляните на версию с относительными единицами измерения; попробуйте изменить размер шрифта и увидите, как с ним изменяется и размер макета.
Три колонки: три цвета
Для трехколоночного макета используется несколько другой подход: границы назначаются непосредственно блоку-контейнеру (можно было бы применить этот метод и для двухколоночного варианта, но в тот момент я об этом не подумал).
HTML:
<div id="container"> <div id="center">Центральная<br />Колонка</div> <div id="leftRail">Левый блок</div> <div id="rightRail">Правый блок</div> </div>
CSS:
#container{
background-color:#0ff;
float:left;
width:500px;
border-left:150px solid #0f0; /* Ширина и цвет левого блока */
border-right:200px solid #f00; /* Ширина и цвет правого блока */
}
#leftRail{
float:left;
width:150px;
margin-left:-150px;
position:relative;
}
#center{
float:left;
width:500px;
margin-right:-500px;
}
#rightRail{
float:right;
width:200px;
margin-right:-200px;
position:relative;
}
Центральная колонка имеет отступ справа (margin-right) в 500 пикселей. Это позволяет левому блоку (leftRail
) обтекать центральную колонку вплоть до ее левого края. Отрицательные отступы выталкивают боковые блоки на место. Есть несколько способов это сделать, но этот будет наиболее удачным для получения резинового
варианта макета, который мы рассмотрим позже.
Я придал блоку-контейнеру свойство обтекания (float) вместо overflow:hidden, чтобы соблюсти высоты колонок, так как боковые блоки выходят за пределы контейнера, обтекая его границы таким образом, что они бы скрывались с помощью свойства переполнения (overflow): IE не скроет их, а Firefox скроет, как и положено.
Теперь для колонок не нужно указывать свойства цвета фона. Поскольку цвета указаны в границах блока-контейнера, высота которого увеличивается до высоты наибольшей колонки, создавать иллюзию одинаковой высоты блоков необязательно.
Резиновая
верстка
Изобразив макет с фиксированными ширинами, я попытался сделать с помощью этой же техники резиновый макет. Боковым блокам придется остаться с жесткими ширинами, так как большинство браузеров не очень-то уважают рамки, заданные в процентах, зато мы можем сделать растягивающейся ширину центрального блока.
CSS:
#container{
background-color:#0ff;
overflow:hidden;
margin:0 100px;
padding-right:150px; /* ширина бокового блока */
}
* html #container{
height:1%; /* Так IE работает как нужно */
}
#content{
background-color:#0ff;
width:100%;
border-right:150px solid #f00;
margin-right:-150px;
float:left;
}
#rail{
background-color:#f00;
width:150px;
float:left;
margin-right:-150px;
}
Разметка такая же, как и в версии для двух колонок с фиксированной шириной, за исключением добавления нескольких слов в контент, чтобы показать, что будет, если блок будет сворачиваться. Код CSS также почти не изменился, за исключением нескольких отличий: контейнер для двух колонок теперь не имеет ширины, так что пришлось добавить height:1%, чтобы IE понял свойство overflow:hidden (здесь использован хак со звездочкой, но можно также использовать условные комментарии чтобы подключить стили специально для IE).
Также добавлены отступы по бокам (но это необязательно). Свойство padding-right сжимает пространство для блока с контентом: так как блок с контентом теперь имеет 100%-ную ширину, если блоку-контейнеру не задано свойство padding, боковой блок будет находиться за пределами контейнера и при этом скрываться. И наконец, ширину блока с контентом из автоматической превращаем в 100%-ную, и добавляем свойство margin-right:-150px боковым блокам.
Как и в случае с двухколоночным макетом с фиксированной шириной, резиновая версия
с левым боковым блоком требует незначительных изменений в CSS. Я добавил простенькую шапку и подвал, можете посмотреть в исходном коде, как это сделано.
Резиновый трехколоночный макет
Метод построения трехколоночного резинового макета с тремя колонками одинаковой высоты назывался многими именами: Святой Грааль
, Один вывереный макет
, Боль в заднице
и так далее… Следующая техника относительно безболезненна, предполагает правильный порядок вывода элементов, не требует использования изображений, и вроде бы без багов.
HTML:
<div id="container"> <div id="center">Центральная колонка</div> <div id="leftRail">Левая<br /> колонка</div> <div id="rightRail">Правая колонка</div> </div>
CSS:
body{
margin:0 100px;
padding:0 200px 0 150px;
}
#container{
background-color:#0ff;
float:left;
width:100%;
border-left:150px solid #0f0;
border-right:200px solid #f00;
margin-left:-150px;
margin-right:-200px;
display:inline; /* Для IE */
}
#leftRail{
float:left;
width:150px;
margin-left:-150px;
position:relative;
}
#center{
float:left;
width:100%;
margin-right:-100%;
}
#rightRail{
float:right;
width:200px;
margin-right:-200px;
position:relative;
}
Отступ и отбивку (margin и padding) теперь вешаем на body. Margin используем для отступов от краев экрана, padding — это ширины боковых колонок. Оставшаяся область это предел ширины контейнера: 100% ширины рабочей области браузера минус отступы и отбивки. В блоке-контейнере установлены рамки и отрицательные отступы, совпадающие с ширинами рамок. Таким образом рамки становятся поверх отбивки (padding) body, и все становится на свои места. Далее мы уже можем позиционировать блоки как угодно.
Следующий пример представляет собой вложенный резиновый двухколоночный макет с шапкой и подвалом. Взгляните на исходный код и убедитесь, как легко вставляется на место и оформляется контент. Во вложенном двухколоночном макете используется техника рамок контейнера. Эта техника позволила мне добавить 2х-пиксельную левую рамку к блоку с контентом и 2х-пиксельную правую рамку к боковому блоку и перекрыть их, создавая таким образом разделитель между ними во всю высоту блоков. Высота разделителя всегда будет совпадать с высотой наибольшего из блоков.
Если вам будет угодно, можете удалить боковые блоки и позиционировать только части контента. Так как боковые блоки на самом деле являются границами контейнера, они будут работать как задумано. Если вам хочется заморочиться еще больше, можете вообще удалить контейнер и задать рамку тегу body. Вы получите трехколоночный макет с одинаковыми высотами колонок и без блока-контейнера! Единственная проблема состоит в том, что фон центральной колонки не может отличаться от фона body — и устранение контейнера вообще делает позиционирование и оформление всех элементов гораздо более сложной задачей… но тем не менее выполнимой.
Должен еще раз заметить, что описанные техники подходят только для случаев с фиксированными ширинами колонок, так как только Opera дает возможность использовать процентные значения в ширинах рамок. Также в боковых колонках нельзя будет использовать изображения в качестве фона, но это обстоятельство возможно изменится с введением свойства border-image в CSS3.
Вот и все, пожалуй: вот вам несколько колонок одинаковой высоты, жесткий или резиновый центральный блок, чистый HTML-код и CSS. Все что понадобилось, это немного подумать нестандартно.
- Автор: Алан Пирс
- Источник: Multi-Column Layouts Climb Out of the Box
- Перевод: Кирилл Харченко