Masonry — вывод блоков в виде кирпичной кладки

В этом уроке у нас пойдет речь про скрипт Masonry.

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

Самый популярный пример, где применение кирпичной кладки можно встретить, это сайт Pinterest. В рамках данного урока, мы научимся создавать такой же эффект.

Приступим...

HTML

Сперва, как обычно, начнем с HTML структуры.

Нам нужно создать некий блок-обертку, который будет оборачивать все наши элементы. В моем коде это блок с классом wrapper. А внутри этого блока уже будут находится те самые элементы, которые мы и хотим расположить в виде кирпичной кладки. Им я дал класс item.

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

<div class="wrapper">
    <div class="item">...</div>
    <div class="item">...</div>
    <div class="item">...</div>
</div>

CSS

Теперь давайте зададим немного стилей.

body {
	font: 16px/1.4 Arial, sans-serif;
}
.wrapper {
	padding: 10px;
}
.item {
	width: 250px; /* Ширину не обязательно указывать именно в пикселях, можно также использовать и проценты */
	border: 2px solid #ccc;
	float: left;
}

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

Отсюда можно сделать вывод, что банальное задание свойства float: left для блоков item, не способно решить нашу проблему.

Поэтому нам на помощь, как раз придет скрипт Masonry.

Подключаем Masonry

Сперва скачайте его на официальном сайте. А затем просто подключите между тегами head.

<script src="path/to/masonry.pkgd.min.js"></script>

После этого, вы можете его проинициализировать. Сделать это можно 3-я способами.

Способ 1 - Инициализация на jQuery

Он подходит в тех случаях, если к вашему сайту уже подключена библиотека jQuery.

$(".wrapper").masonry({
  itemSelector: ".item",
  columnWidth: ".item"
});

C помощью $(".wrapper") мы отбираем блок-обертку, который оборачивает все наши элементы.

А затем прописываем еще 2 параметра:

itemSelector - указывает класс тех самых блоков, которые мы и хотим выводить в виде кирпичной кладки.

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

Например так:

$(".wrapper").masonry({
  itemSelector: ".item",
  columnWidth: 254
});

Это будет означать, что ширина нашей колонки составляет 254 пикселя.

Способ 2 - Инициализация на чистом JS

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

var msnry = new Masonry(".wrapper", {
  itemSelector: ".item",
  columnWidth: ".item"
});

Способ 3 - Инициализация в HTML

Этот способ заключается в установке специального data атрибута для нашего блока-обертки. В нем мы и указываем требуемые нам опции.
Помимо этого атрибута, мы также должны задать еще один класс - это js-masonry.

<div class="wrapper js-masonry" data-masonry-options='{ "itemSelector": ".item", "columWidth": ".item" }'>
    <div class="item">...</div>
    <div class="item">...</div>
    <div class="item">...</div>
</div>

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

Настройка Masonry

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

Пример 1 - Меняем ширину для некоторых блоков

Сейчас, после инициализации, все блоки у нас имеют одинаковую ширину, но иногда возникает необходимость, чтобы какой-то отдельный элемент или группа элементов имела ширину, допустим, как два обычных блока.

Чтобы было понятней, про что я говорю, просто взгляните на пример.

Мы видим, что блок с красным текстом, по ширине занимает пространство, как два обычных блока. Как это можно реализовать?

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

.item_w2 {
	width: 504px;
}

Примечание: Почему же ширину мы указали именно 504px, а не 500px? Ведь ширина обычных блоков 250px, следовательно 250 * 2 = 500.
Все дело в том, что мы еще для наших элементов задавали рамку в 2px, в частности нас интересует рамка проходящая слева и справа, так вот, ее тоже нужно брать в расчет. Именно поэтому у нас и выходит значение в 504px. Если бы у наших элементов, был задан еще и padding, то нам также пришлось бы взять его в расчет.

В общем если вы не совсем понимаете данную концепцию, то я вам советую заново изучить тему "за счет чего формируется ширина у блочных элементов в CSS".

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

<div class="wrapper">
    <div class="item">...</div>
    <div class="item item_w2">...</div>
    <div class="item">...</div>
</div>

Пример 2 - Добавляем отступ по горизонтали между блоками

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

Ее нам необходимо указывать на этапе инициализации плагина, т.е. примерно так:

$(".wrapper").masonry({
  itemSelector: ".item",
  columnWidth: ".item",
  gutter: 10
});

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

.item {
	margin-bottom: 10px;
}

Пример 3 - Выравниваем наши блоки по центру

Если вы хотите чтобы блоки были выровнены по центру и при изменении размеров окна браузера, также динамически центровались, то вам нужно сделать следующее.

В CSS для блока wrapper задайте:

.wrapper {
	margin: 0 auto;
}

А при инициализации плагина укажите новую опцию isFitWidth: true.

$(".wrapper").masonry({
    itemSelector: ".item",
    columnWidth: ".item",
    isFitWidth: true
});

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

Примечание: данный подход будет работать только лишь в том случае, если ширина наших блоков item будет задана в абсолютных единицах, таких как пиксели. Если вы зададите ширину, например в процентах, то ничего работать не будет.

Пару рекомендаций

Совет 1 - Как решить проблемы с изображениями?

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

Чтобы этого избежать, есть 3 способа:

1. Задавать размеры для каждого изображения (ширину и высоту). Если вы это сделаете, то даже если картинка не успеет подгрузиться, то браузер для нее все равно зарезервирует место и из-за этого Masonry уже верно все рассчитает и проблемы, описанной выше не возникнет.

Лично я применяю только этот подход.

2. Инициализацию скрипта нужно повесить на событие load().

$(window).load(function(){
	$('.wrapper').masonry({
	  columnWidth: ".item",
	  itemSelector: '.item'
	});
});

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

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

3. Проверять загрузку изображений с помощью дополнительного скрипта.

Для этого есть специальный скрипт imagesLoaded, с его помощью мы сможем проверить, загружены ли все изображения и только после этого делать инициализацию.

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

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

Резюмирую, если вы не хотите проблем при использовании скрипта Masonry с изображениями, то обязательно применяйте один из перечисленных способов.

Совет 2 - Как создать кирпичную кладку на чистом CSS?

В данном уроке мы разбирали реализацию с помощью JS, но на самом деле можно нечто подобное реализовать и на CSS. Правда это будет актуально только в том случае, если вам необходимо создать кирпичную кладку в две колонки (если надо больше, то тут стоит применять только JS).

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

Смысл его в следующем, нам необходимо для нечетных элементов задать свойство float: left, а для четных - float: right.

Таким образом, у нас как раз будет создана двухколоночная структура в стиле кирпичной кладки.

Вот полный CSS:

body {
	font: 16px/1.4 Arial, sans-serif;
}
.wrapper {
	padding: 10px;
    width: 508px;
}
.item {
	width: 250px;
	border: 2px solid #ccc;
}
.item:nth-child(odd){  /* Отбираем только нечетные элементы */
	float: left;
}
.item:nth-child(even){ /* Отбираем только четные элементы */
	float: right;
}

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

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

Понравилась статья?

Тогда оставь свой комментарий или расскажи о ней своим друзьям и коллегам.

Комментарии ВКонтакте

Добавить комментарийКомментариев (11)

Геннадий 23 марта в 07:45

Спасибо большое Александр за афигительный урок! Респект!!

Ответить

Aleks 3 января в 16:58

Сорри, нашел свой косяк!!

Ответить

Aleks 3 января в 16:56

Подскажите пожалуйста. У меня wrapper 960px, две колонки, и ширина одной колонки 460px. когда я ставлю gutter 60, то в длину колонки уже не входят. Как можно сделать что бы они входили??
Заранее благодарю за ответы!!!

Ответить

Виталий 30 ноября 2015 г. в 10:45

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

Ответить

Игорь 22 июня 2015 г. в 01:51

Александр, могли бы вы сделать пару уроков по ГОСТ Р 52872-2012 (требования доступности для инвалидов по зрению). Сейчас это целая проблема (даже прокуратура подключается). Пример на сайте http://minjust.ru/ .

Ответить

Ilhom 19 июня 2015 г. в 12:42

Спасибо, за урок. Ваши уроки всегда интересные и информативные. Теперь о плагине.Год назад пришлось его использовать в одном проекте. Тогда была 3.1.5 версия. Не очень корректно работала. Тогда использовал другой плагин - Grid-A-Licious 3. Он мне больше понравилься. ИМХО

Ответить

Виктор 18 июня 2015 г. в 16:32

Большое спасибо. Многие моменты при работе со скриптами мне стали более понятны.

Ответить

Николай 17 июня 2015 г. в 22:32

С помошью флексбоксов можно на чистом css сделать

Ответить

Александр Пауков 17 июня 2015 г. в 22:59

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

Ответить

Сергей 17 июня 2015 г. в 11:24

Спасибо Александр, ка всегда ваши уроки очень понятные и полезные. Практически на все вопросы я могу найти ответ в ваших видео-уроках.

Ответить

Erik 11 февраля 2016 г. в 15:54

У меня ничего не вышло. Все сделать как показано. Не выходит

Ответить
Наверх

Скачивание материалов доступно
только подписчикам!

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

Подписка бесплатная и займет у вас
не более 1 минуты

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

Для получения доступа, заполните форму ниже. Введите свое настоящее имя и e-mail

« Вернуться назад

Проверьте свой почтовый ящик

и подтвердите подписку

После этого вы сразу же получите доступ ко всем материалам этого блога

Введите e-mail, который вы указывали при подписке

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

« Вернуться назад