Skip to content

Masonry Kit ​

Framework-agnostic masonry/bento grid layout engine — ResizeObserver-measured, transform-positioned, with bento-style colSpan/rowSpan cards built in from the start, not bolted on later. Vue 3, React, and Nuxt adapters share one core. You own the card markup and content; this only measures it and packs it.

Features ​

  • Skyline packing generalized to spans — classic shortest-lane masonry, extended to bento-style colSpan/rowSpan cards from the first line of code, not bolted on afterward; 'balanced' (default) picks the least-filled lane group for each item, 'ordered' keeps strict round-robin instead
  • One axis-agnostic engine for both directions — direction: 'vertical' (columns) and 'horizontal' (rows) share the same core geometry, not two separate algorithms to keep in sync
  • Transform-based positioning, not CSS columns/Grid masonry — every item is measured via ResizeObserver and placed with transform: translate(), so a reflow never triggers layout of its own, and an image's height changing after load re-packs the grid automatically
  • Virtualization built in — a two-phase layout for large lists: items outside the visible range (± overscan) skip real DOM measurement entirely and use an estimated size instead, so relayout stays cheap regardless of list size
  • FLIP-animated reflow — items slide into their new slot instead of teleporting, and fade in/out on add/remove, entirely via inline styles (zero required CSS)
  • SSR-safe — a CSS columns approximation renders before the engine exists (server-side, and for the one client frame before the first real measurement), then swaps to the exact layout in the same frame it measures
  • Keyboard-reorderable items — pick up/move/drop via space and arrow keys, announced through a live region; pointer/touch drag was tried and deliberately left out — masonry's skyline packing makes a live pointer-drag reflow inherently unpredictable (which neighbor ends up where depends on the exact path the cursor took, not just where it landed) in a way a discrete keyboard step isn't
  • Vue, React, and Nuxt adapters over one core — a <MasonryGrid> component/hook pair for each framework, all re-exporting the full core surface, so installing just one adapter package reaches the framework-agnostic layer too
  • Zero peer dependencies in core — @macrulez/masonry-kit-core runs anywhere, including outside a framework entirely