Заметки веб-работника
4 мая 2006

Табличная верстка блоками

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

Ключевой вопрос

Что же мешает блочной верстке победоносно шагать по планете? Существует множество препятствий. Но, пожалуй, особняком среди них стоит проблема, кое-где сравнимая даже не больше не меньше как с поиском Грааля. Узкое место – создание горизонтальных блоков одинаковой высоты, т.е. реализация той самой что ни на есть табличной сущности, которая порой необходима при верстке сайта, к примеру, в случае классического 3-хколоночного макета:

трехколоночный макет

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

<div id="main" class="table">
   <div class="tr">
      <div id="first" class="td">
         <!-- первая колонка -->
      </div>
      <div id="second" class="td">
         <!-- вторая колонка -->
      </div>
      <div id="third" class="td">
         <!-- третья колонка -->
      </div>
   </div>
</div>

Согласно стандартам CSS, для того чтобы превратить этот набор дивов в таблицу, достаточно указать в классах соответствующие отображения: display:table;, display:table-row; и display:table-cell;.

Но я не случайно назвал такой подход непопулярным. «Табличники» увидят в приеме лишь ненужное «изобретение велосипеда», ярые же поборники nu skool посчитают этот путь идеологически неверным, тем более, что на первый взгляд кажется, что он ведет в тупик, браузеры от Microsoft display:table; не поддерживали, и в ближайшее время поддерживать не планирует, а значит, есть возможность отказаться от табличных шаблонов и этой ситуацией грех не воспользоваться.

Со многими возражениями можно согласиться, но, тем не менее, нельзя не заметить и очевидные плюсы «табличного» подхода, главными среди которых я вижу:

  • разделение содержания от представления;
  • возможность верстать «табличные» макеты любой сложности;
  • простая реализация.

Решения

Пункт «простая реализация», пожалуй, вызовет наибольшие сомнения, c «правильными браузерами» все понятно, но существует ли действительно простое решение для Internet Explorer? Существует.

К примеру, рассмотрим следующую конструкцию:

<!-- Для большей наглядности я использую лишь один див-контейнер -->
<div id="main" class="table">
   <div id="first" class="td">
      <!-- первая колонка -->
   </div>
   <div id="second" class="td">
      <!-- вторая колонка -->
   </div>
   <div id="third" class="td">
      <!-- третья колонка -->
   </div>
</div>

Для того чтобы расположить блоки горизонтально, выровняв при этом их высоту, т.е. сымитировать табличное поведение в IE, достаточно определить стилевые классы

div.table{
   height:0;
}

div.td{
   height:100%; 
   float: left;
}
указать ширину для колонок и… всё. Пример 1 иллюстрирует данную технику (Внимание! Работает только в режиме обратной совместимомости – Quirks Mode) для варианта, когда трем колонкам задана ширина в 200px.

Рассмотрим более «жизненную» задачу: допустим, каркас должен быть растянут по ширине на 100%, ширина первой колонки – 200px, третьей – 30%, вторая же пусть занимает свободное пространство. Решение для IE может выглядеть так (дополним стилевой лист):

#main{
   width:100%;
}

#first{
   width:200px;
}

#second{
   width:expression(document.body.clientWidth*(1-0.3) - 200);
}

#third{
   width:30%;
}

См. пример 2. Или же так:

#main{
   width:100%;
}
#first{
   position:relative;
   z-index:1;
   width:200px;
}

#second{
   width:100%;
   margin:0 -30% 0 -200px; 
   padding:0 30% 0 200px;
}

#third{
   width:30%;
}

См. пример 3.

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

div.table{
   height:0;
}
div.tr{
   height:0;
}
/* не для IE */
div.table[class] {height:auto; display: table;}
div.tr[class] { height:auto; display: table-row;}
div.td[class] {float:none; display: table-cell;}

div.td{
   height:100%; 
   float:left;
}
#main{
   width:100%;
}
#first{
   position:relative;
   z-index:1;
   width:200px;
}
#second{
   width:100%;
   margin:0 -30% 0 -200px; 
   padding:0 30% 0 200px;
}
/* не для IE */
#second[id]{
   width:auto;
   margin:0;
   padding:0;
}
#third{
   width:30%;
}

См. пример 4.

Итог

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


Теги: CSS

Комментарии

1
Андрей Лысенко (Чт, 8 Ноя 2007 18:37:53 +0200)
 

Только недавно узнал, что трюк с height:0 – это один из способов выставления значения true Microsoft'овскому свойству hasLayout.

Подробнее о hasLayout можно почитать здесь: http://www.satzansatz.de/cssd/onhavinglayout.html либо здесь: http://www.habrahabr.ru/blog/webdev/24553.html

2
Дмитрий (Вт, 14 Апр 2009 19:27:42 +0300)
 

Пожалуйста, если вас не затруднит, поясните мне глупому, зачем давать дивам "табличные" display когда можно просто использовать сами таблицы? Я неоднократно видел статьи с аналогичным содержанием, но по-прежнему для меня это выглядит как какое-то дикое извращение!

Не вижу тут отделения содержания от представления, поскольку структура вышеприведенного html  кода с дивами повторяет структуру нормальной таблицы, только вместо <tr>, <td> - дивы с соответствующими классами. Да и потом, если нам нужно, чтобы данные выглядели "таблично", зачем же темнить душой?
Выигрыша в компактности кода тоже не вижу, только если самый мизер...

Возможно вам надоело отвечать на подобные комментарии, но все же буду благодарен, если уделите мне минутку.

3
Андрей Лысенко (Ср, 15 Апр 2009 16:27:03 +0300)
 

>>зачем давать дивам "табличные" display когда можно просто использовать сами таблицы?

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

Ключевой момент здесь – отделение содержания от представления. Приведенный в статье набор дивов не повторяет «структуру нормальной таблицы», это – обычная древовидная структура, она просто ассоциируется с таблицей (так как в html использование табличных тегов превращает эту конструкцию в таблицу). Важно понимать, что вопрос не в противопоставлении дивов табличным тегам, а в достижении нужного уровня абстракции. Т.е. примеры в статье должны восприниматься не как «дивы вместо таблиц», а как «дивы как таблицы» (они ведь могут и отображаться и «как что-то еще» в отличие от табличных тегов). Отображая «дивный» шаблон «таблично», вы не темните душой, часто вы просто отображаете его же еще и «в столбик» и «по диагонали», либо имеете такую возможность.

Надеюсь, я смог ответить на ваш вопрос.

4
Дмитрий (Сб, 18 Апр 2009 17:13:58 +0300)
 

Спасибо, я понял идею!

5
Алексей (Сб, 18 Апр 2009 23:33:41 +0300)
 

Идея хорошая, я даже уже реализовал кое-что подобное перед прочтением этой статьи, но решил тут протестировать реализованное в не совсем правильных (а в очень правильных:) новых браузерах типа firefox3 и chrome. Заметил, что все съезжает, а если точнее, то подвал наезжает на среднюю часть и даже отдельные его части по разному смещаются вверх.
В ie(7) и опере(9.64) все выглядит хорошо (и причем, одинаково).
Попробую добавить "display: table; display: table-row; display: table-cell;" в нужных местах, т.к. пока обходился без них.

6
Lacran (Пн, 13 Июл 2009 20:51:11 +0300)
 

Пример 4 - то, что искал, спасибо. Надеюсь, что эффект выравнивания не пропадет при вкладке в них пучков дивов.

7
Kirby (Пн, 20 Июл 2009 23:16:31 +0300)
 

Отличная работа. Давно хотел найти подобно решение! В верстке не силен, но думаю что пример хорошо ;)

8
Владислав Трушин (Вт, 4 Авг 2009 1:18:28 +0300)
 

Мне идея понравилась, но:

1. Всё равно же это не симулирует нам полноценную таблицу. Я люблю использовать вертикал-элайн: бейслайн в форме (Например, Логин: пароль). Это мне даёт свободу от разностей в величинах шрифтов лейбла и текста инпута — я просто знаю, что они всегда будут выравниваться по базовой линии. Здесь же придется это дотачивать.

2. Ну и конечно экспрешены, тем более здесь не одноразовые. Если все таблицы на сайте средней сложности заменить на вот такие блоки, он будет кряхтеть и сопеть ) Мог бы понадобиться такой метод, мне кажется, в "умных" формах. Например, когда при изменении размера экрана лейблы, стоявшие слева от инпута должны прыгнуть вверх ) В этом случае может быть ещё можно использовать <div>ы, а в ЦСС экспрешеннами просто переназначать их на <table> когда лейбл слева от инпута, и обратно в <div>ы, когда лейбл сверху ))

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

Сорри, за массивность коммента )

9
gvv100 (Вт, 18 Авг 2009 21:40:48 +0300)
 

Статья интересная, да вот только не работает если заголовок страницы начинается с <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
<html xmlns="http://www.w3.org/1999/xhtml";>. Интересно почему?

10
Андрей Лысенко (Ср, 19 Авг 2009 6:14:45 +0300)
 

Я указал, что прием работает только в режиме обратной совместимости. О режимах см., к примеру, здесь http://xhtml.ru/2005/05/05/doctype_quirks/

Страницы c комментариями:  1  2

_______

Вы можете оставить свой отзыв по данной статье:

  Имя
  E-mail (не публикуется)
  Веб-сайт

Комментарий (Теги форматирования не поддерживаются)