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+.

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

Добавить комментарий

  • Здравствуйте! У меня не получается подключить masonry. После нажатия download открывается файл с кодом ."https://unpkg.com/masonry-layout@4.2.1/dist/masonry.pkgd.min.js". При попытке загрузить этот файл через торрент или download мастер, выдаёт ошибку, как будто он вообще не видит его. Не могу понять, что делаю не так. Как загрузить его к себе на комп? Спасибо

    • Если открывается файл с кодом прямо в браузере, просто сохраните этот файл нажав Ctrl+S.
      Далее появится окно, в котором нужно выбрать место на компьютере, куда этот файл будет сохранен.

      • 10.02.2018 11:49

        Спасибо, всё получилось! А то уже расстроилась. Такой урок хороший, Александр! О результате напишу позже:)

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

  • 03.01.2017 16:58

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

  • 03.01.2017 16:56

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

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

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

  • 19.06.2015 12:42

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

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

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

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

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

    • 11.02.2016 15:54

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