Верстка плитками и вариант решения на JQuery

Ильдар Сарибжанов | 01.12.2013

Верстка плитками и вариант решения на JQuery

Одним из последних веяний в веб-дизайне, да и в GUI в принципе, является плиточная верстка. Win8 яркий тому пример. Наверное, с точки зрения дизайна это очень клево и стильно. Так уж исторически сложилось, что я не дизайнер, я верстальщик. И вот именно в верстке плитками есть много тонкостей и сложностей.

Сначала выскажу свое видение вариантов такой верстки.

1. Если в дизайне все блоки имеют одинаковый размер.

Проблем я не вижу. Жмем блоки друг к другу с помощью float:left и пляшем.

2. Блоки имеют одинаковую ширину, но разную высоту.

Можно, конечно, воспользоваться таким же вариантом с float:left, но в результате вы получите следующую проблему:

Та-да-да-дан

Это особенности свойства float: left, кстати, если использовать display: inline-block, ситуация будет ровно такой же, поскольку элементы хоть и применяют свойства блочных элементов, но в линию выстраиваются как строчные, т.е. по строкам, такое вот масло масленное.

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

Лично я решал эту проблему колоночным вариантом верстки: 4 колонки (или столько колонок, сколько вам нужно) и в них добавляются ваши блоки контента. Выглядеть это будет примерно вот так:

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

Перейдем к последнему типу плиточной верстки

3. Блоки имеют различную высоту и ширину.

Не совсем различную, а есть некоторый базовый блок, а все остальные имеют размер кратный базовому. По крайней мере, мне хочется верить, что все обстоит именно так =) Как быть тут? Понятно, что вариант 1 и 2 нам не подходят. Но дизайнеры, нормальные дизайнеры, понимают, что можно сделать, а что нельзя. Соответственно, верстальщик может выделить в макете некоторую закономерность или упорядоченность. Сразу приведу пример как я решал проблему неодинаковых блоков.

Так что же тут происходит?

Можно идти очень сложным, но логичным путем, сначала выделяем большой блок, равный одной строке, в нашем случае этот блок будет равен 4 базовых блока в ширину и 2 базовых блока в высоту. Затем, для верхних двух маленьких блоков создаем собственную обертку, чтобы они располагались один под другим. Для верхних правых такая же история.

Я в данном примере, исключил большой блок 2х4, он только загромождает верстку, поэтому структура такая. (Дальше размеры блоков будут обозначаться NxM, где N — ширина в базовых блоках и M — высота в базовых блоках)

  • Блок 1х2 с float: left
    • Внутри него 2 блока 1х1 без float: left
  • Блок 2х2 с float: left
  • Снова блок 1х2 с float: left
    • Внутри него 2 блока 1х1 без float: left
  • Затем переход но новую строку и начинает ее блок 2х2 c float: left
  • И т.д.

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

Вот и у меня возникла мысль: «Ну ее нафиг, такую структуру, надо искать плагины плиточной верстки!»

Я не любитель искать, особенно, когда в голове уже сидит идея как можно сделать свой велосипед и по какой логике он должен работать. Вот так и рождаются стопицот квадратноколесых велосипедов.

Как оно работает?

Есть некоторый стандартный набор элементов: во-первых обертка с классом tile_content, которая наполняется нашими элементами. Затем внутрь обертки помещается много-много необходимых элементов с обязательным классом b_itemtile и еще одним классом, который говорит нашему скрипту о размерах блока b_itemtile_1_1, где первая цифра ширина, а вторая высота. А больше ничего по верстке нет. Круто? Я считаю, что круто! Мне очень нравится такая простая верстка, тем более, что я прямо вижу как классно наполнять эту верстку =)

	<div class="tile_content">
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_2_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_2_2 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_4_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_3_3 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_4 b_itemtile"></div>
		<div class="b_itemtile_1_3 b_itemtile"></div>
		<div class="b_itemtile_1_2 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_3_4 b_itemtile"></div>
		<div class="b_itemtile_1_1 b_itemtile"></div>
		<div class="b_itemtile_1_4 b_itemtile"></div>
		<div class="b_itemtile_4_1 b_itemtile"></div>
	</div>

А самое классное это количество стилей для этой верстки

.tile_content{position: relative; outline: 1px solid #f00; overflow: hidden;}
	.b_itemtile{position: absolute; background: #aaa;}

И все! Все остальное сделает скрипт.

Приводить код скрипта не буду, скажу только, что он работает. И делает это следующим образом. У него есть пока всего 2 настройки: количество колонок и расстояние между блоками. Ну как настройки? В коде скрипта есть две переменные, которые и отвечают за эти параметры.

  • Сначала вычисляется размер базового блока исходя из ширины контейнера, количества колонок и расстояния между ними
  • Затем всем блокам выставляется необходимый размер, в соответствии с базовым блоком и расстоянием между блоками
  • А затем начинается магия позиционирования!
  • Магия проста, помним пункт 2 про колонки и как их заполнять. Тут все тоже самое, за исключением того, что физически нет никаких колонок, они вымышленные. Ищем ту колонку которая самая маленькая в данный момент, затем смотрим чтобы наш блок вошел по своим габаритам в соседние колонки и если все хорошо, пихаем этот блок на законное место при помощи абсолютного позицирнирования.
  • Предыдущий шаг повторяется пока не будут спозиционированны все блоки по очереди
  • Высота родительского блока выставляется равной высоте самой большой колонки
  • Вуаля!

tilepage

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

tile_point

Но если дизайн составлен под руководством здравого смысла, управляемого логикой, то на выходе красота, да и только.

Вот ссылка на архив с рабочим примером. К тому же я потихоньку изучаю Git и дам ссылку на github, есть вероятность, что к моменту прочтения поста, на гитхабе будет версия более похожая на плагин и более функциональна. Хотя меня пока устраивает и этот вариант, мои задачи он выполняет!