WordPress как на ладони
Наставник Трепачёв Д.П., phphtml.net wordpress jino

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

masonry - скрипт для вывода блоков в виде кладки
Оглавление:

Встречали сайты, где блоки разных размеров выводятся в контейнер, максимально рационально заполняя пространство?

Пример блоков Масонри →

Сделать такой вывод позволяет скрипт David'a DeSandro, который называется Masonry (с англ. кирпичная кладка). Также, наглядный пример можете посмотреть на официальном сайте скрипта. На офф. сайте вы найдете полную документацию на английском.

Masonry — это Javascript библиотека, позволяющая выводить HTML блоки в компактно-сложенном виде. Скрипт анализирует высоту каждого блока и максимально экономя пространство располагает его.

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

Masonry работает самостоятельно без использования библиотек, но также может использоваться как jQuery плагин.

В этом посте я сделаю перевод главной страницы офф-сайта, которая объясняет как начать работать со скриптом.

к началу

Masonry на Javascript

Подключение Masonry

Эти пакеты установки, содержат все что нужно, для использования Masonry:

Скачивайте js файл и подключайте его к вашему сайту:

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

Для WordPress подключать лучше используя функцию wp_enqueue_script():

function mason_script() {
	// wp_register_script('masonry', '/path/to/masonry.pkgd.min.js');
	// верхняя строка не нужна, потому что в WordPress masonry есть в комплекте по умолчанию, поэтому можно просто его подключить.
	wp_enqueue_script('masonry');
}
add_action( 'wp_enqueue_scripts', 'mason_script' );
к началу

HTML

Masonry работает с элементами контейнера, для которых указан один и тот же класс item:

<div id="container">
  <div class="item">...</div>
  <div class="item w2">...</div>
  <div class="item">...</div>
  ...
</div>

Класс можно указать любой, главное при вызове определить опцию itemSelector : '.item'.

CSS

Для блоков контейнера нужно указать ширину. Ширину нужно подбирать соответствующую контейнеру и параметру columnWidth (ширина колонки):

.item { width: 25%; }
.item.w2 { width: 50%; }

Включение Masonry (Инициализация)

Чтобы скрипт начал работать его нужно применить к нашему контейнеру. Запуск скрипта в виде экземпляра на чистом javascript делает так:

var container = document.querySelector('#container');
var msnry = new Masonry( container, {
  // Настройки
  columnWidth: 200,
  itemSelector: '.item'
});

В этом случае конструктор экземпляра содержит 2 аргумента: columnWidth (ширина колонки) и itemSelector (класс блоков в контейнере с которыми будет работать Masonry). Это не все опции, остальные смотрите в документации или ниже на этой странице.

Инициализация через HTML

Masonry можно запустить не используя Javascript, прямо из HTML, указав class js_masonry контейнеру и указав параметры в атрибуте data-masonry-options:

<div id="container" class="js-masonry"
  data-masonry-options='{ "columnWidth": 200, "itemSelector": ".item" }'>

Опции установленные в HTML должны быть в формате JSON. Аргументы должны быть в кавычках "itemSelector":. Имейте ввиду, что значение аттрибута HTML должно быть в одинарных кавычках ('), потому что свойства JSON используют двойные кавычки (").

Инициализация через jQuery

Для использования Masonry не нужно jQuery, но если вам удобнее работать с jQuery, masonry работает с ним как плагин.

var $container = $('#container');
// Инициализация
$container.masonry({
  columnWidth: 200,
  itemSelector: '.item'
});

Чтобы получить экземпляр используйте метод .data('masonry'):

var msnry = $container.data('masonry');

Инициализация для блоков с изображениями

Так как картинки подгружаются отдельно от HTML кода, применение "Масонри" для блоков с картинкой обычно вызывает ошибку - наложение одного блока на другой. Так происходит потому что Масонри срабатывает до того, как картинка в блоке подгружается, блоку устанавливается высота, а затем картинка "рушит" эту высоту. Решить эту проблему можно несколькими способами:

Способ 1

Установить для всех изображений размеры жестко: ширину и высоту в пикселях.

Способ 2

Повесить обработку Масонри на событиеload. Код для jQuery:

 jQuery(window).load(function(){
	 jQuery('.masonry').masonry({ columnWidth:310, itemSelector:'.box, .item' });
 });

Минус этого способа в том, что тут скорее всего придется ждать загрузки всего "окна": jQuery(window).load. Использовать load отдельно для элемента редко допустимо, потому что jQuery будет интерпретировать его как AJAX функцию load. Чтобы этого избежать используйте 3-й пример.

Способ 3

Инициализировать работу Масонри, после того, как все картинки будут загружены. А для проверки загрузки использовать дополнительный JS скрипт imagesLoaded. Код:

var container = document.querySelector('#container');
var msnry;
// Инициализация Масонри, после загрузки изображений
imagesLoaded( container, function() {
  msnry = new Masonry( container );
});

Код для jQuery:

var $container = $('#container');
// Инициализация Масонри, после загрузки изображений
$container.imagesLoaded( function() {
  $container.masonry();
});

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

к началу

Свойства

Обязательные свойства это: columnWidth and itemSelector. Все остальные можно использовать по желанию:

itemSelector(строка) (обязательный)
Определяет какой дочерний элемент контейнера будет использован при построении кладки. Элемент нужно указывать, чтобы исключить другие элементы контейнера, которые используются для установки размеров см. "columnWidth": ".grid-sizer".
По умолчанию: нет
columnWidth(число/элемент/селектор в виде строки) (обязательный)
Ширина колонки в пикселях: "columnWidth": 60. Если установить селектор или элемент, masonry будет использовать ширину установленного элемента: "columnWidth": ".gutter-sizer".Masonry рассчитывает внешнюю ширину блоков, с учетом css свойств border, padding, margin.
По умолчанию: нет
containerStyle(объект)
CSS стили которые применяются к контейнеру. Чтобы отменить применение masonry стилей к контейнеру укажите containerStyle: null
По умолчанию: { position: 'relative' }
gutter(число/элемент/селектор в виде строки)
Расстояние между элементами, подобное margin-right. Пример: "gutter": 10
По умолчанию: 0
hiddenStyle(объект)
Стили применяемые к спрятанным элементам.
По умолчанию: { opacity: 0, transform: 'scale(0.001)' }
isFitWidth(логический)
Устанавливает ширину контейнера равную доступному числу колонок, рассчитанную из ширины элементов контейнера. Когда установлен параметр, вы можете отцентровать контейнер через CSS. Заметка: это свойство не работает, если элементам контейнера установлена ширина в %, нужно в пикселях: width: 120px. Также, опция columnWidth должна быть установлена в фиксированное значение, например: columnWidth: 120.
По умолчанию: false
isInitLayout(логический)
Включает подстройку блоков во время инициализации. Установите в false, чтобы скрипт не строил кирпичную кладку при инициализации, так вы сможете использовать методы и добавлять события перед обработкой элементов контейнера.
По умолчанию: true
isOriginLeft(логический)
Контролирует горизонтальное расположение блоков. По умолчанию блоки расставляются с лева на права. Установите в false, чтобы расположить блоки с права на лева.
По умолчанию: true
isOriginTop(логический)
Контролирует вертикальное расположение блоков. По умолчанию блоки располагаются сверху вниз. Установите в false, чтобы блоки располагались снизу вверх.
По умолчанию: true
isResizeBound(логический)
Связывает расположение блоков с изменениями размеров окна.
По умолчанию: true
stamp(элемент/массив элементов/строка селектор/NodeList)
Определяет какие блоки нужно зафиксировать при выводе. Это специальные элементы к которым не будет применен эффект masonry. "stamp": ".stamp"
По умолчанию: нет
transitionDuration(строка)
Продолжительность перехода (скорость анимации), когда блоки меняют позицию или появляются. Нужно устанавливать в формате времени для CSS. Чтобы отменить всю анимацию установите в 0: transitionDuration: 0
По умолчанию: '0.4s'
visibleStyle(объект)
Стили, которые будут применены при показе скрытых элементов.
По умолчанию: { opacity: 1, transform: 'scale(1)' }
к началу

Масонри на чистом CSS

C недавних пор, практически все браузеры понимают свойство CSS column-count, смотрите сами.

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

Суть такова.

У нас есть такой HTML код:

<div class="masonry">
   <div class="item">Lorem ipsum dolor sit amet, consectetur adipisicing elit.</div>
   <div class="item">...</div>
   ...
   <div class="item">...</div>
</div>

И мы подключаем для него такие css стили:

/* Контейнер блоков Masonry */
.masonry {
	column-count: 4; // сколько колонок нужно?
	column-gap: 1em; // промежуток между блоками (справа или слева)

	/* тоже самое с нужными префиксами на 18 марта 2016 */
	-webkit-column-count: 4; -moz-column-count: 4; column-count: 4;
	-webkit-column-gap: 1em; -moz-column-gap: 1em; column-gap: 1em;
}
/* Блоки Masonry */
.masonry .item {
	display: inline-block; // важно!
	width: 100%;           // важно!
	margin-bottom: 1em;
	background-color: #eee;
}

Смотреть реальный пример →

Минусов у этого варианта хватает

Пробежимся по минусам этого метода и чем он уступает масонри.

  1. Поддержка браузеров, на сегодня (2016 г.) отличная, но все же не полная...

  2. Любую анимацию, нужно будет дописывать вручную.

  3. Главный минус column-count и, собственно, причина, по которой нельзя использовать этот способ вместо masonry в большинстве случаев - это направление блоков.
    Если у masonry читается по горизонтали:
    1 2 3
    4 5 6
    То в column-count по вертикали:
    1 3 5
    2 4 6
    С таким подходом использовать с хронологической точки зрения не вариант.

    Из комментария

  4. Динамическое добавление элементов в блок, например при AJAX погрузке, сбивает с толку... Т.е. Масонри, добавляет новые элементы после текущих и не трогает текущие, так нет путаницы что добавилось, а что нет. А вот этот вариант, путает элементы. Например, у нас есть 3 колонки и 30 элементов - условно по 10 в каждой колонке. Добавляем еще 10 и они добавятся не равномерно во все 3 колонки, не затрагивая предыдущее расположение элементов, а добавятся в HTML, а затем браузер перестроит расположение. При этом в первую колонку может попасть 1 элемент, во вторую 2, а в третью 8. В результате, после динамического добавления элементов почти всегда получается путаница: что было и что добавилось...
    Поэтому, если планируете подгружать элементы аяксом - этот вариант рассматривать не стоит!

Продвижение сайта www.seop.ru

продвижение сайта www.seop.ru

www.seop.ru

Masonry - вывод html блоков в виде кирпичной кладки 34 комментария
Полезные 5 Все
  • campusboy1734 cайт: wp-plus.ru
    @

    Спасибо за статью!

    Небольшая опечатка:

    Заметка: Токая же ошибка может быть при использовании

    -1
    Ответитьгод назад #
  • Denis Semenov13 cайт: denisemenov.com

    Главный минус column-count и, собственно, причина, по которой нельзя использовать этот способ вместо masonry в большинстве случаев - это направление блоков.
    Если у masonry читается по горизонтали:
    1 2 3
    4 5 6
    То в column-count по вертикали:
    1 3 5
    2 4 6
    С таким подходом использовать с хронологической точки зрения не вариант. sad

    1
  • Paxanb cайт: kino60.com
    @

    При заходе на страницу масонри иногда отрабатывает неверно (например не просчитываются отступы). Перезагрузив страницу 1-2 раза - получается корректный результат. Иногда при заходе на страницу сразу отображается как надо. Иногда опять перестает корректно просчитывать. Пробовал различные комбинации открытия страниц, открытия браузера. Такой глюк\фича проявилась в Гугл Хроме и Опере. В Фаерфоксе каждый раз отрабатывает как надо.

    Плагинов кеширования в wp не стоит. Масонри подключал и вверху страницы и внизу.

    Есть идеи, в чем может быть проблема?

    1
    • Paxanb cайт: kino60.com
      @

      Пояснение: картинки жестко заданы по ширине и высоте. Высота новости меняется за счет текста.

      В итоге сделал так (скорее всего быдлокод, да простят меня нормальные программисты)

      Вот такая штука у меня корректно заработала только в фаерфоксе. Поэтому я ее оставил.

      <div id="content_masonry" class="js-masonry" data-masonry-options='{ "singleMode": true, "itemSelector": ".masonry_box", "gutter": 20}'>

      В хроме и опере стабильно работает этот код

          <script type="text/javascript">   
      		var container = document.querySelector('#content_masonry');
      		var msnry = new Masonry( container, { "singleMode": true, "itemSelector": ".masonry_box", "gutter": 20});
      	</script>

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

      P.S.

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

          <style type="text/css">
      		#content_masonry{
      			width: 628px;
      			margin-top: 50px;
      		}
      
      		#content_masonry .masonry_box {
      			width: 303px;
      			margin-bottom: 20px;            
      		}   
      	</style>
      
      <script src="https://npmcdn.com/imagesloaded@4.1/imagesloaded.pkgd.min.js"></script>
      	<script type="text/javascript">
      		jQuery( document ).ready( function( $ ) {
      		var $container = $('#content_masonry').masonry({
      			singleMode: true,
      			itemSelector: '.masonry_box',
      			gutter: 20
      		});
      		$container.imagesLoaded( function() {
      			$container.masonry();  
      			});
      	});
      	</script>

      P.P.S.
      Буду признателен, если кто-нить укажет на мои ошибки.

      1
  • Андрей

    Вставляю:

    var $container = $('#container');
    // Инициализация Масонри, после загрузки изображений
    $container.imagesLoaded( function() {
      $container.masonry();
    });

    Получаю ошибку: Uncaught TypeError: $container.imagesLoaded is not a function

    Ответить4 месяца назад #
    • Kama4472

      А для проверки загрузки использовать дополнительный JS скрипт imagesLoaded.

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

      Ответить4 месяца назад #
  • Юра cайт: teatrcdr.ru

    Paxanb и автор вы мои спасители! Спасибо большое!!!!

    Ответить2 месяца назад #

Здравствуйте, !

Ваш комментарий