Пропустить навигацию

Многоколоночный макет, выходящий за пределы блока

23.02.2007 , , ,

by Alan Pearce

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

Проект, над которым в недавнем прошлом мне пришлось работать, требовал создания тянущегося макета, с двумя колонками одинаковой высоты, каждая со своим фоновым цветом. Как обычно бывает в подобных ситуациях, невозможно точно сказать, которая из колонок будет длиннее. Я просмотрел статью Faux Columns, однако требовался именно тянущийся макет. Далее я просмотрел статью One True Layout, однако, похоже, она была с ошибками, содержала избыточный код разметки и требовала слишком много хаков под мои требования. Я даже подумал использовать JavaScript для создания колонок одинаковой высоты, но это было бы неправильно. Отчаявшись, я чуть было не применил таблицы!

Но нет, нашлось все же решение. Мне потребовалось просто поразмыслить о том, что находится за пределами блока. Так что же за блоком есть? Границы. Если бы мне удалось, используя свойство float сместить колоночный div за границы основного контента, я смог бы имитировать колонки одинаковой высоты, независимо от того, которая из них длиннее.

Если все это звучит уже знакомо, то только лишь потому, что подобный метод был представлен Douglas Livingstone и расширен Holly и John Bergevin с статье Position Is Everything. Если следовать данной теории, метод, представленный здесь использует более “чистую”, с небольшой степенью вложенности разметку, включая тянущиеся двухколоночные варианты макетов и в целом однозначно лучше, описанного в статье One-True-Layout. Вот как это все выглядит.

HTML код:

<div id="container">
  <div id="content">This is<br />some content</div>
  <div id="rail">This is the rail</div>

</div>

Код CSS:

#container{
  background-color:#0ff;
  overflow:hidden;
  width:750px;
}
#content{
  background-color:#0ff;
  width:600px;
  border-right:150px solid #f00;
  /* The width and color of the rail */
  margin-right:-150px; /* Hat tip to Ryan Brill */
  float:left;
}
#rail{
  background-color:#f00;
  width:150px;
  float:left;
}

Я создал правую границу в div’е content такой же ширины и цвета, как и блок rail, затем сместил этот блок rail свойством float влево, Правая граница margin-right:-150px блока content позволила блоку rail сместиться влево на освобожденное место. Если блок content будет длиннее блока rail, вместе с ним вырастет и граница, т.о. блок rail тоже вытянется. Я установил фон блока container и content одинаковыми для того, чтобы если блок rail является более высоким, то блок container “вырастет” вместе с ним. Для того, чтобы блок rail выровнялся по левому краю необходимо внести небольшие изменения только в таблицу стилей CSS в зависимости от того, что длиннее, либо content, либо rail.

Можете просмотреть данный пример в действии либо взглянуть на «тянущуюся» версию макета; попробуйте поменять размер шрифта, и посмотрите, как будет меняться макет.

Три колонки: три цвета

Трехколоночный макет требует немного другого подхода, а именно граница применяется непосредственно к блоку container. (Я мог бы сделать это и с двухколоночным макетом, однако я не думал об этом на тот момент).

HTML код:

<div id="container">
  <div id="center">CENTER<br />COLUMN CENTER</div>
  <div id="leftRail">LEFT RAIL</div>

  <div id="rightRail">RIGHT RAIL</div>

</div>

Код CSS:

#container{
  background-color:#0ff;
  float:left;
  width:500px;
  border-left:150px solid #0f0;
  /* The width and color of the left rail */
  border-right:200px solid #f00;
  /* The width and color of the right rail */
}
#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;
}

Пример в действии.

Центральная колонка имеет границу -500px. Это позволяет левому блоку rail располагаться с левого края центральной колонки. Отрицательные границы вставляют боковые колонки на свои места. Существует несколько способов добиться этого, но данный кажется наиболее оптимальным решением при переходе позже к «тянущемуся» макету

Для блока container я установил свойство float: left вместо overflow:hidden. Сделано это потому, что колоночные блоки расположены за пределами блока container, обтекая его границы, поэтому они просто исчезнут с использование свойства overflow: в IE боковые колонки не исчезают, однако в Firefox’е корректно пропадают.

Для колонок не нужно устанавливать цвет фона. Поскольку цвета устанавливаются для блока container, который «растет» вместе с самой длиной колонкой, появляется иллюзия равной высоты всех колонок.

«Тянущийся» макет

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

Код CSS:

#container{
  background-color:#0ff;
  overflow:hidden;
  margin:0 100px;
  padding-right:150px; /* The width of the rail */
}
* html #container{
  height:1%; /* So IE plays nice */
}
#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;
}

Пример в действии.

Размета точно такая же как и при двух-колоночном макете фиксированной ширины, за исключением блока content. Таблица стилей CSS претерпела незначительные изменения, однако обратим внимание на несколько важных различий: блок container не имеет фиксированной ширины и добавлена высота в 1%, чтобы IE правильно обработал свойством overflow:hidden (Я использовал хак *html, однако можно было бы использовать conditional comments для включения стилей понятных только IE)

Я также добавил границы по бокам, как опцию. Отступ справа padding-right создает дополнительное пространство для блока и блок content заполняет все что осталось, поскольку имеет ширину 100%, если бы не было отступа, то боковой блок ушел бы за пределы блока container и исчез бы. Наконец, ширина блока content переключается на 100% и добавляется граница к боковой колонке margin-right:-150px

Также как и в двух-колоночном макете фиксированной ширины, версия left-rail требует внесения небольших изменений в CSS. Я добавил просто header и footer и теперь можно просмотреть исходник и увидеть пример в действии.

Трех-колоночный «тянущийся» макет

Трех-колоночные макеты, с колонками равной высоты назывались по всякому: “Holy Grail”, “One True Layout”, “pain in the @$$”… Предложенный ниже метод является относительно несложным, использует правильный порядок в разметке, не требует использования фоновых изображений и похоже, не имеет багов.

The HTML:

<div id="container">
  <div id="center">Center Column Content</div>

  <div id="leftRail">Left<br /> Sidebar</div>

  <div id="rightRail">Right Sidebar</div>
</div>

The 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; /* So IE plays nice */
}
#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;
}

В body на этот раз используются граница и отступ. Граница «вдавливает» макет между краями экрана, а отступ является шириной боковых колонок. Оставшееся место — это ширина, до которой может увеличиваться блок container: 100% ширины браузера минус граница и отступ. В блоке container я установил границы и бордюры одинаковой ширины но с разными знаками. Это накладывает границы поверх отступов в body, расставляя все на свои места. Затем мы можем размещать любые блоки.

Следующий пример показывает вложенный «тянущийся» двух-колоночный макет с header’ом и footer’ом. Посмотрите в код, и поймете как просто наполнить и стилизовать этот макет. Вложенный «тянущийся» двух-колоночный макет использует технику с границей в блоке container. Это позволяет мне добавить левый бордюр в 2px в блоке content и правый бордюр в 2px в блоке rail и перекрыть их, создав разделитель полной высоты между ними. Этот разделитель вытянется вместе с боковыми колонками независимо от того, какая из них длиннее.

Еще раз обращаю внимание, что этот метод работает только с колонками фиксированной ширины, поскольку только Opera понимает ширину границ в %-х. Блок rail может и не иметь фонового рисунка, однако это может измениться в свойстве border-image property in CSS3

Итак, мы имеем много-колоночные макеты с колонками равной высоты, фиксированные и тянущиеся центральные блоки, чистая разметка CSS. И все, что нужно было для этого сделать, так это немного поразмыслить за пределами блока.

Пример в действии.

Источник alistapart.com

Перевод — Дмитрий Папуца

Оригинал статьи

Translated with the permission of A List Apart Magazine and the author[s].