Skip to content

Masonry Kit

v0.1.4UI-компонентыVanilla JSVueNuxtReact

Библиотека masonry/bento-сеток для Vue 3, React и Nuxt — карточки разной высоты сами упаковываются в ровные колонки, с широкими bento-карточками, плавной анимацией перестроения и поддержкой больших списков.

Masonry Kit
Начать знакомство →
npm install @macrulez/masonry-kit-core
01 — Назначение

Когда это пригодится

Сетка карточек с естественно разной высотой обычно означает либо CSS columns (которая заполняет сверху вниз, колонка за колонкой — редко совпадает с визуальным порядком чтения), либо более тяжёлую masonry-библиотеку со своими требованиями к разметке. Masonry Kit измеряет уже существующие карточки и расставляет их, оставляя разметку и стилизацию полностью вашими.

Галерея карточек в духе Pinterest

Карточки естественно разной высоты нужно упаковать в визуально сбалансированные колонки — skyline-упаковка кладёт каждую карточку в наименее заполненную колонку, вместо произвольного порядка заполнения у CSS columns.

Бенто-дашборд с карточками разного размера

Часть карточек шире остальных — через colSpan/rowSpan они участвуют в той же skyline-упаковке, что и обычные, а не размещаются вручную в CSS Grid-шаблоне, который приходится держать в синхроне с данными.

Лента из сотен или тысяч карточек

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

Masonry-сетка, которая не мигает при загрузке страницы

До и во время гидратации рендерится приближение через CSS columns, а в тот же кадр, когда движок реально измеряет карточки, оно сменяется точной раскладкой — без заметного скачка.

02 — Фичи

Коротко о главном

Skyline-упаковка с бенто-спанами

Skyline-упаковка с бенто-спанами

Классическая masonry-упаковка «в наименее заполненную колонку», обобщённая на карточки с colSpan/rowSpan с первой строчки кода, а не пристроенная поверх позже. 'balanced' (по умолчанию) выбирает наименее заполненную группу колонок под каждую карточку, 'ordered' — строгий round-robin.

Один движок на оба направления

Один движок на оба направления

direction: 'vertical' (колонки) и 'horizontal' (строки) используют одну и ту же геометрию ядра, а не два отдельных алгоритма, которые приходится держать в синхроне.

Transform-позиционирование, а не CSS columns/Grid

Transform-позиционирование, а не CSS columns/Grid

Каждая карточка измеряется через ResizeObserver и расставляется через transform: translate(), так что reflow никогда не вызывает собственный layout — а изменение высоты картинки после загрузки само пересобирает сетку.

Виртуализация для больших списков

Виртуализация для больших списков

Двухфазная раскладка: карточки вне видимой области (± overscan) вообще пропускают измерение DOM и используют оценку размера — пересчёт остаётся дешёвым независимо от размера списка.

FLIP-анимация reflow

FLIP-анимация reflow

Карточки плавно съезжают на новое место вместо телепортации, и проявляются/исчезают при добавлении/удалении — целиком через инлайн-стили, без обязательного CSS.

Клавиатурная пересортировка

Клавиатурная пересортировка

Взять/переместить/отпустить через пробел и стрелки, с озвучиванием через live-регион — указательный drag намеренно не реализован: skyline-упаковка делает live-перетаскивание мышью непредсказуемым (кто окажется соседом, зависит от точного пути курсора, а не только от точки посадки) так, как дискретный шаг клавиатурой — нет.

03 — Быстрый пример

Как это работает

Карточки разной высоты — упаковка сама собой

createMasonryEngine() измеряет карточки через ResizeObserver и упаковывает их skyline-алгоритмом — без ручного расчёта колонок и без угадывания с CSS columns.

basic.ts
import { createMasonryEngine } from '@macrulez/masonry-kit-core'

const container = document.querySelector('#grid') as HTMLElement
const engine = createMasonryEngine(container, { columns: 'auto', minLaneSize: 240 })

engine.setItems([
  { id: 'a', el: document.querySelector('#card-a') as HTMLElement },
  { id: 'b', el: document.querySelector('#card-b') as HTMLElement },
])

Бенто-карточки — та же упаковка

Более широкая карточка с colSpan участвует в той же самой skyline-упаковке, что и обычные — отдельного CSS Grid-шаблона, который нужно держать в синхроне с данными, не требуется.

bento.ts
engine.setItems([
  { id: 'hero', el: heroEl, colSpan: 2 },
  { id: 'a', el: aEl },
  { id: 'b', el: bEl },
])