npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mannisto/astro-masonry

v1.1.1

Published

A masonry layout component for Astro.

Readme

Astro Masonry

banner

Astro npm version license

Astro-native masonry layout component with shortest-column balancing, responsive breakpoints, and accessible arrow key navigation.

Installation

npm install @mannisto/astro-masonry
pnpm add @mannisto/astro-masonry
yarn add @mannisto/astro-masonry

Usage

---
import { Masonry } from "@mannisto/astro-masonry/components"
---

<Masonry autoColumns={280} columns={3}>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

autoColumns fills as many columns as the container fits at the given minimum width. columns caps the maximum at 3.

Props

| Prop | Type | Default | Description | |---|---|---|---| | columns | number | 1 | Number of columns in fixed mode, or maximum cap when used with autoColumns. Defaults to unlimited when autoColumns is set | | gap | number \| string | "1rem" | Gap between items. Numbers are treated as px | | breakpoints | Record<number, number> | — | Map of minWidth → columns. Mobile-first, stacks on top of columns | | autoColumns | number \| string | — | Fill as many columns as fit at this minimum width. Numbers are treated as px | | sequential | boolean | false | Distribute items left to right, top to bottom instead of shortest-column | | aria-label | string | — | Sets aria-label on the root element | | role | string | — | Sets role on the root element | | class | string | — | Class names on the root element |

Examples

Fixed columns

<Masonry columns={3}>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

Balanced distribution Items are distributed into the shortest column, keeping overall height balanced.

Responsive columns

columns sets the base, breakpoints adds on top. Keys are minimum viewport widths in px.

<Masonry
  columns={1}
  breakpoints={{ 640: 2, 1024: 3 }}
>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

Auto-sizing columns

Fills as many columns as the container fits at the given minimum width. Responds automatically to container resize.

<Masonry autoColumns={280}>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

Auto-sizing with a maximum

columns limits the maximum number of columns when used with autoColumns.

<Masonry
  autoColumns={280}
  columns={4}
>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

Auto-sizing with a responsive maximum

breakpoints can adjust the cap at different viewport widths.

<Masonry
  autoColumns={280}
  columns={1}
  breakpoints={{ 640: 2, 1024: 4 }}
>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

Sequential order

Items are distributed left to right, top to bottom. Useful when reading order matters.

<Masonry columns={3} sequential>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

Sequential distribution Items are distributed left to right, top to bottom, preserving reading order.

Dynamic items

Items can be added to the grid after initial render. Append them directly to any [data-masonry-column] element, then dispatch a masonry:refresh event on the root to redistribute:

const root = document.querySelector("[data-masonry]")
const column = root.querySelector("[data-masonry-column]")

const card = document.createElement("div")
column.appendChild(card)

root.dispatchEvent(new CustomEvent("masonry:refresh"))

When the width of the grid changes, the grid re-layouts automatically, and the new items are included without any extra steps.

Layout updates

The grid re-layouts when its width changes, because the items then get a new height. A change in height alone does not move the items, for example an edit in the browser DevTools.

If the height of an item changes after the first layout, for example when a card opens or a lazy image loads, dispatch masonry:refresh on the root to balance the columns again.

If the page can get a scrollbar, add scrollbar-gutter: stable to your page. A scrollbar that comes and goes changes the width of the grid, and a new layout can then add or remove the scrollbar again:

html {
  scrollbar-gutter: stable;
}

Keyboard navigation

When focus is inside the grid, arrow keys move between items:

| Key | Behaviour | |---|---| | ArrowUp | Previous item in the same column | | ArrowDown | Next item in the same column | | ArrowLeft | Item in the previous column at the same vertical position | | ArrowRight | Item in the next column at the same vertical position |

Keyboard navigation

Accessibility

Screen readers navigate items in column order, matching the visual layout. Use aria-label and role to identify the grid as a landmark or feed.

<Masonry
  columns={3}
  aria-label="Photo gallery"
  role="feed"
>
  {items.map((item) => (
    <div>{item}</div>
  ))}
</Masonry>

License

MIT © Ere Männistö