Design system

Masonry

Pinterest-like masonry layout grid.

Masonry Examples

Copy-ready examples with live previews.

Basic usage (cols + gapScale)

Defines column count and spacing scale.

Live preview

Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
Card 7
Card 8
Card 9
Card 10
Card 11
Card 12

Basic masonry

import Masonry from "@/packages/ui/src/_components/grid/masonry/Masonry";

export default function Example() {
  return (
    <Masonry cols={3} gapScale={4}>
      <div className="cssnt-masonry__item">Card 1</div>
      <div className="cssnt-masonry__item">Card 2</div>
      <div className="cssnt-masonry__item">Card 3</div>
      <div className="cssnt-masonry__item">Card 4</div>
    </Masonry>
  );
}

Spacing preset (variants)

Use variants to switch between dense / normal / spacious spacing.

Live preview

variants applies a spacing preset. If set, it takes priority over gapScale.
variants="dense"
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
variants="normal"
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
variants="spacious"
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

variants

import Masonry from "@/packages/ui/src/_components/grid/masonry/Masonry";

export default function Example() {
  return (
    <Masonry cols={4} variants="spacious">
      <div className="cssnt-masonry__item">Card 1</div>
      <div className="cssnt-masonry__item">Card 2</div>
      <div className="cssnt-masonry__item">Card 3</div>
      <div className="cssnt-masonry__item">Card 4</div>
    </Masonry>
  );
}

Priority (variants > gapScale)

When variants is provided, gapScale is not applied.

Live preview

Here gapScale is ignored because variants is provided.
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
Card 7
Card 8

variants wins over gapScale

import Masonry from "@/packages/ui/src/_components/grid/masonry/Masonry";

export default function Example() {
  return (
    <Masonry cols={3} variants="dense" gapScale={8}>
      {/* gapScale is ignored because variants is set */}
      <div className="cssnt-masonry__item">Card 1</div>
      <div className="cssnt-masonry__item">Card 2</div>
      <div className="cssnt-masonry__item">Card 3</div>
      <div className="cssnt-masonry__item">Card 4</div>
    </Masonry>
  );
}

Full width helper (isFull)

Adds an `is-full` helper class.

Live preview

isFull adds a helper class for full-width layouts inside constrained wrappers.
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6

isFull

import Masonry from "@/packages/ui/src/_components/grid/masonry/Masonry";

export default function Example() {
  return (
    <div style={{ maxWidth: 520 }}>
      <Masonry cols={2} variants="dense" isFull>
        <div className="cssnt-masonry__item">Item A</div>
        <div className="cssnt-masonry__item">Item B</div>
      </Masonry>
    </div>
  );
}

Interactive playground

Quick way to test combinations in the docs (cols / variants / gapScale / isFull).

Live preview

cols
variants
gapScale(ignored when variants is set)
isFull
Card 1
Card 2
Card 3
Card 4
Card 5
Card 6
Card 7
Card 8
Card 9
Card 10
Card 11
Card 12

Playground

import { useState } from "react";
import Masonry from "@/_components/grid/masonry/Masonry";

type MasonryVariants = "dense" | "normal" | "spacious" | undefined;

export default function Example() {
  const [cols, setCols] = useState<1 | 2 | 3 | 4 | 5>(3);
  const [variants, setVariants] = useState<MasonryVariants>(undefined);
  const [gapScale, setGapScale] = useState<0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8>(4);

  return (
    <Masonry
      cols={cols}
      variants={variants}
      gapScale={variants ? undefined : gapScale}
      isFull
    >
      <div className="cssnt-masonry__item">Card 1</div>
      <div className="cssnt-masonry__item">Card 2</div>
      <div className="cssnt-masonry__item">Card 3</div>
    </Masonry>
  );
}

On this page

Masonry Props

Lightweight masonry-like layout utility that composes CSS classes and renders a single <div> container.

Class composition order: base `cssnt-masonry` → cols → variants → gapScale (only when variants is not set) → `is-full` (when isFull=true).

If `variants` is provided, `gapScale` is ignored.

Masonry props
PropTypeRequiredDefaultDescription
cols1 | 2 | 3 | 4 | 5Non/aNumber of masonry columns (`cssnt-masonry--cols-*`). (Values: 1, 2, 3, 4, 5)
variants"dense" | "normal" | "spacious"Non/aSpacing preset class (`cssnt-masonry--dense/normal/spacious`). When set, it takes priority over `gapScale`. (Values: dense, normal, spacious)
gapScale0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8Non/aGap scale (`cssnt-masonry--gap-*`). Only applied when `variants` is not set. (Values: 0, 1, 2, 3, 4, 5, 6, 7, 8)
isFullbooleanNofalseAdds `is-full` helper class.
childrenReact.ReactNodeNon/aContent inside the masonry container.
customStylesReact.CSSPropertiesNon/aInline styles for the root container (`style`).