Angular

Masonry — это библиотека для создания динамических сеток с плотным расположением элементов, где высота элементов может быть разной. В отличие от стандартного CSS-флоата, Masonry автоматически располагает элементы так, чтобы минимизировать вертикальные пробелы между ними, создавая эффект “кирпичной кладки”.

Подключение библиотеки

Для использования Masonry необходимо подключить саму библиотеку и стили для контейнера и элементов сетки:

<link rel="stylesheet" href="styles.css">
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>

Контейнер сетки должен иметь уникальный класс или идентификатор, а элементы сетки — общий класс.

<div class="grid">
  <div class="grid-item">Элемент 1</div>
  <div class="grid-item">Элемент 2</div>
  <div class="grid-item">Элемент 3</div>
</div>

CSS для сетки и элементов:

.grid {
  width: 100%;
}
.grid-item {
  width: 200px;
  margin-bottom: 16px;
  background-color: #ddd;
}

Инициализация Masonry

Инициализация выполняется через конструктор Masonry, куда передаются контейнер и параметры конфигурации:

const grid = document.querySelector('.grid');
const masonry = new Masonry(grid, {
  itemSelector: '.grid-item',
  columnWidth: 200,
  gutter: 16,
  fitWidth: true
});

Основные параметры:

  • itemSelector — селектор для элементов сетки.
  • columnWidth — ширина колонки, может быть фиксированной или вычисляться автоматически.
  • gutter — расстояние между элементами.
  • fitWidth — если true, сетка будет центрироваться внутри контейнера.

Работа с динамическим контентом

Для сеток, где элементы добавляются после загрузки страницы, Masonry предоставляет методы appended и layout:

const newItem = document.createElement('div');
newItem.classList.add('grid-item');
newItem.textContent = 'Новый элемент';
grid.appendChild(newItem);
masonry.appended(newItem);
masonry.layout();

Метод appended позволяет Masonry корректно расположить новый элемент без полной переработки сетки. layout можно вызвать для перерасчёта всех позиций, если размеры элементов изменились.

Адаптивная сетка

Для адаптивных сеток можно использовать процентные значения или медиазапросы в CSS, а Masonry будет автоматически перестраивать колонки при изменении ширины контейнера:

.grid-item {
  width: 48%; /* Два элемента в ряд на маленьких экранах */
}
@media (min-width: 768px) {
  .grid-item {
    width: 23%; /* Четыре элемента в ряд на больших экранах */
  }
}

Для динамического изменения размеров можно использовать метод layout при событии resize:

window.addEventListener('resize', () => {
  masonry.layout();
});

Использование Masonry с Angular

В Angular интеграция Masonry требует внимательного подхода, так как работа идет через компонентную архитектуру. Оптимальный способ — создать сервис для управления сеткой и директиву для элементов:

// masonry.service.ts
import { Injectable } from '@angular/core';
import Masonry from 'masonry-layout';

@Injectable({ providedIn: 'root' })
export class MasonryService {
  private masonryInstance: Masonry | null = null;

  init(gridSelector: string, options: any) {
    const grid = document.querySelector(gridSelector) as HTMLElement;
    this.masonryInstance = new Masonry(grid, options);
  }

  layout() {
    this.masonryInstance?.layout();
  }

  appended(element: HTMLElement) {
    if (this.masonryInstance) {
      this.masonryInstance.appended(element);
      this.masonryInstance.layout();
    }
  }
}

Директива для элементов:

// masonry-item.directive.ts
import { Directive, ElementRef, AfterViewInit } from '@angular/core';
import { MasonryService } from './masonry.service';

@Directive({
  selector: '[appMasonryItem]'
})
export class MasonryItemDirective implements AfterViewInit {
  constructor(private el: ElementRef, private masonryService: MasonryService) {}

  ngAfterViewInit() {
    this.masonryService.appended(this.el.nativeElement);
  }
}

Компонент с сеткой:

// grid.component.ts
import { Component, AfterViewInit } from '@angular/core';
import { MasonryService } from './masonry.service';

@Component({
  selector: 'app-grid',
  templateUrl: './grid.component.html',
  styleUrls: ['./grid.component.css']
})
export class GridComponent implements AfterViewInit {
  constructor(private masonryService: MasonryService) {}

  ngAfterViewInit() {
    this.masonryService.init('.grid', {
      itemSelector: '.grid-item',
      columnWidth: 200,
      gutter: 16,
      fitWidth: true
    });
  }
}

События Masonry

Masonry предоставляет несколько событий для контроля состояния сетки:

  • layoutComplete — вызывается после перерасчёта расположения.
  • removeComplete — после удаления элементов.
  • appendComplete — после добавления новых элементов.

Пример подписки на событие:

masonry.on('layoutComplete', (items) => {
  console.log('Сетка обновлена', items);
});

Оптимизация производительности

  • Минимизировать количество пересчётов layout.
  • Использовать imagesLoaded для работы с изображениями, чтобы Masonry учитывал их размеры:
imagesLoaded(grid, () => {
  masonry.layout();
});
  • Группировать добавление новых элементов, а не добавлять по одному.

Совместимость с другими библиотеками

Masonry хорошо сочетается с библиотеками для ленивой загрузки изображений, анимации и фильтров. Для Angular удобно использовать комбинацию с RxJS для динамического управления потоком данных и Masonry-сеткой.


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