@macrulez/masonry-kit-vue
v0.1.4
Published
Vue 3 <MasonryGrid> component and useMasonry composable for masonry/bento grid layouts
Readme
Masonry Kit Vue

Vue 3 <MasonryGrid> component and useMasonry() composable for
masonry/bento grid layouts, built on
@macrulez/masonry-kit-core.
You own the card markup — this only measures it and positions it.
Part of the masonry-kit
monorepo. See also
@macrulez/masonry-kit-nuxt
if you're on Nuxt, and the
playground
for a live example (bento spans, virtualization, a horizontal shelf,
keyboard reordering, SSR fallback).
Features
<MasonryGrid>— slot-per-item component: wraps each item's#itemslot content in a measured wrapper<div>, forwards it to the engine, and applies its resolved positionuseMasonry()— low-level composable for when the slot-per-item component doesn't fit; you own the item elements, this wires the engine to a container and keeps it synced with reactiveitems- Bento spans —
colSpan/rowSpanper item, same as core - Virtualization —
options.virtualizerenders a wrapper/slot only for currently visible items; the rest exist only as an estimate inside the engine, not in the DOM - FLIP-animated reflow, add/remove fade —
options.animate(defaulttrue); a removed item's wrapper stays mounted fortransitionDurationso core's leave fade-out actually gets to play instead of being cut short by an immediate unmount sortablekeyboard reordering — every item becomes keyboard-reorderable (space/enter to pick up, arrow keys to move, space/enter to drop, escape to cancel), announced through a live region; never mutatesitems— emitsreorderwith the new array, same idea asv-model- SSR-safe out of the box — renders a CSS
columnsapproximation until the engine's first real layout, no<ClientOnly>needed - The full
@macrulez/masonry-kit-coresurface, re-exported —createMasonryEngine,optionsEqual,resolveSsrColumns,setMasonryDefaults, and their types are all available straight from@macrulez/masonry-kit-vuetoo, no separate core install needed
When you'd reach for this
@macrulez/masonry-kit-core's engine with Vue's own reactivity wired on top — a reactive items array in, positioned cards out.
- A gallery/feed of cards with naturally differing heights —
<MasonryGrid>packs them into balanced columns reactively; add/remove/reorderitemsand it relayouts on its own, no manual relayout call needed. - A bento-style dashboard with some cards wider than others —
colSpanon the item object is the whole API, no separate CSS Grid template to keep in sync with the data. - A list large enough that mounting every card at once is expensive —
options.virtualizekeeps only the currently visible window's cards actually in the DOM. - A reorderable list that needs to be keyboard-accessible, not just draggable —
sortablegives pick-up/move/drop via the keyboard with ARIA live-region announcements built in, no separate accessibility pass. - A Nuxt/SSR page rendering this grid — no flash of unstyled or stacked content; a CSS
columnsapproximation renders immediately server-side, swapped for the real layout the instant the engine measures on the client.
Installation
Requires Vue ^3.3.0.
npm install @macrulez/masonry-kit-vueQuick start
<script setup lang="ts">
import { MasonryGrid } from '@macrulez/masonry-kit-vue'
const items = [{ id: 'a' }, { id: 'b', colSpan: 2 }, { id: 'c' }]
</script>
<template>
<MasonryGrid :items="items" :options="{ columns: 'auto', minLaneSize: 240 }">
<template #item="{ item }">
<MyCard :data="item" />
</template>
</MasonryGrid>
</template>More examples
Bento spans
<MasonryGrid :items="items" :options="{ columns: 4, gap: 14 }">
<template #item="{ item }">
<DemoCard :label="item.id" :height="item.size" />
</template>
</MasonryGrid>colSpan on any item stretches it across that many lanes; add/remove/shuffle items and every card reflows live.
Virtualizing a large list
<MasonryGrid :items="items" :options="{ virtualize: { overscan: 800 }, minLaneSize: 200 }">
<template #item="{ item }">
<Card :item="item" />
</template>
</MasonryGrid>Only items inside the visible range (± overscan) actually get a wrapper/slot mounted — the rest exist only as an estimate until they scroll into view.
Keyboard-reorderable items (sortable)
<script setup lang="ts">
import { ref } from 'vue'
import { MasonryGrid, type MasonryGridItem } from '@macrulez/masonry-kit-vue'
const items = ref([{ id: 'a' }, { id: 'b' }, { id: 'c' }])
function onReorder(next: MasonryGridItem[]) {
items.value = next
}
</script>
<template>
<MasonryGrid :items="items" sortable @reorder="onReorder">
<template #item="{ item }">
<Card :item="item" />
</template>
</MasonryGrid>
</template>Tab to a card, Space/Enter to pick it up, arrow keys to move it, Space/Enter to drop, Escape to cancel — no pointer/touch drag: 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.
useMasonry() — the low-level escape hatch
<script setup lang="ts">
import { useTemplateRef } from 'vue'
import { useMasonry } from '@macrulez/masonry-kit-vue'
const container = useTemplateRef('container')
const cardA = useTemplateRef('cardA')
const cardB = useTemplateRef('cardB')
const { engine } = useMasonry(container, {
items: [
{ id: 'a', el: cardA },
{ id: 'b', el: cardB },
],
columns: 3,
})
</script>
<template>
<div ref="container">
<div ref="cardA">A</div>
<div ref="cardB">B</div>
</div>
</template>items[].el accepts a ref, a getter, or a plain value (MaybeRefOrGetter) — it can start out null before the element mounts and useMasonry will pick it up automatically once it resolves.
setMasonryDefaults()
Package-wide fallback for any MasonryOptions field, read underneath an explicit options prop/argument. This is what
@macrulez/masonry-kit-nuxt's
module options configure under the hood — call it directly if you're not using Nuxt but still want project-wide defaults:
import { setMasonryDefaults } from '@macrulez/masonry-kit-vue'
setMasonryDefaults({ gap: 12, animate: true, transitionDuration: 200 })Documentation & links
- 📖 Full documentation: npm.vuecraft.ru/en/packages/masonry-kit
- 🌐 VueCraft: vuecraft.ru/en
- 👤 Author: macrulez.ru/en
- 💻 GitHub: macrulezru/masonry-kit/packages/vue
- 📦 NPM: @macrulez/masonry-kit-vue
- 🐛 Issues: github.com/macrulezru/masonry-kit/issues
License
MIT
💖 Support the project
Open source takes time and effort. If this library saves you time or brings value, consider supporting further development.
Thank you for being part of this journey. ❤️
