masonix
Examples

Product Grid

Ecommerce-style cards with automatic responsive columns.

Product grids usually need reliable card width more than shortest-column balancing. Use Masonry with columnWidth and maxColumns.

New

Furniture

Linen lounge chair

$420

Rating 4.8 / 5.0

Low stock

Lighting

Halo task lamp

$148

Rating 4.9 / 5.0

Bundle

Workspace

Ceramic desk set

$86

Rating 4.7 / 5.0

Popular

Travel

Canvas weekend bag

$196

Rating 4.6 / 5.0

Gift pick

Home

Soft wool throw

$112

Rating 4.9 / 5.0

Limited

Decor

Frosted glass vase

$74

Rating 4.8 / 5.0

Example

import { clsx } from 'clsx';
import { Masonry } from 'masonix';

type Product = {
  id: string;
  name: string;
  category: string;
  price: string;
  rating: string;
  badge: string;
  gradient: string;
  height: number;
};

function ProductCard({ product }: { product: Product }) {
  return (
    <article
      className={clsx(
        'overflow-hidden',
        'rounded-xl border',
        'border-zinc-200 bg-white text-zinc-950 dark:border-zinc-800 dark:bg-zinc-950 dark:text-zinc-50',
      )}
    >
      <div
        className="relative"
        style={{ height: product.height, background: product.gradient }}
      >
        <span
          className={clsx(
            'absolute left-3 top-3',
            'px-2 py-1',
            'rounded-full',
            'text-xs font-medium',
            'bg-white/85 text-zinc-900',
          )}
        >
          {product.badge}
        </span>
      </div>
      <div className="p-4">
        <div className="flex items-start justify-between gap-3">
          <div>
            <p className="text-xs text-zinc-500 dark:text-zinc-400">
              {product.category}
            </p>
            <h3 className="mt-1 text-sm font-semibold">{product.name}</h3>
          </div>
          <span className="shrink-0 text-sm font-semibold">
            {product.price}
          </span>
        </div>
        <p className="mt-3 text-xs text-zinc-500 dark:text-zinc-400">
          Rating {product.rating} / 5.0
        </p>
      </div>
    </article>
  );
}

export function ProductGrid({ products }: { products: Product[] }) {
  return (
    <Masonry
      items={products}
      columnWidth={180}
      maxColumns={3}
      gap={16}
      itemKey={(product) => product.id}
      render={({ data }) => <ProductCard product={data} />}
    />
  );
}

When to use

Use this for catalogs, collections, marketplace cards, and browse pages where all items can render up front.

Notes

  • Keep card actions inside the render component.
  • Use itemClassName for shared wrapper effects.
  • Use MasonryBalanced only if product card heights vary enough to look uneven.

On this page