@cssints/masonry

A masonry layout for cssints: masonry(), a chain member of cssints/plugin scope(). Items of different heights are packed into as many columns as fit, each item under the shortest column, with no row gaps. It is CSS Grid Level 3's grid lanes (display: grid-lanes) where the browser has them, and CSS multi-column layout where it does not. No JavaScript, no media queries.

import { cn, p } from "cssints" with { type: "cssints" };
import { masonry } from "@cssints/masonry" with { type: "cssints" };

export const photos = masonry();
export const wall = cn(masonry().columns("12rem").gap(4), p(2));
@layer _.k {
  ._masonry-lanes {
    columns: var(--masonry-min);
    gap: var(--masonry-gap);
    --masonry-min: 16rem;
    --masonry-gap: 1rem;
    display: grid-lanes;
    grid-template-columns: repeat(auto-fill, minmax(min(var(--masonry-min), 100%), 1fr));
  }
  /* only when a browserslist target lacks grid lanes */
  @supports not (display: grid-lanes) {
    ._masonry-lanes > * {
      display: inline-block;
      inline-size: 100%;
      vertical-align: top;
      break-inside: avoid;
      margin-block-end: var(--masonry-gap);
    }
  }
}
@layer _.a {
  ._x {
    --masonry-min: 12rem;
  }
  ._y {
    --masonry-gap: 1rem;
  }
}

Methods

Each once, in any order:

Method Default What it is
columns 16rem the least width of a column: as many columns as fit, never wider than the container
gap 1rem the space between columns and between an item and the next in its column (one value for both)

Both take a length (no percentage: the fallback's columns and margins cannot use one the same way). A lone number in gap is a step of the spacing scale (0.25rem), as in padding. Tokens go where a length does. The types check each method, and the build checks it again. A method in media() or another condition sets the custom property under it.

Browsers

Rules

Limits

cd packages/masonry && bun run test   # fixtures through the engine (output for both kinds of targets, conflicts, build errors, a build), and the type test via bun run typecheck
bun run test:browsers                 # Chrome, Firefox and WebKit through playwright-core: items pack with no row gaps

Credits

The layout is CSS Grid Layout Module Level 3 (the W3C CSS Working Group), display: grid-lanes as WebKit ships it. Nothing is copied.