Examples
Article Cards
Mixed-height editorial cards using measured shortest-column placement.
Editorial cards often have unpredictable text length. MasonryBalanced
measures the rendered card and places the next item in the shortest column.
Example
import { clsx } from 'clsx';
import { MasonryBalanced } from 'masonix';
type Article = {
id: string;
title: string;
section: string;
excerpt: string;
readTime: string;
accent: string;
};
function ArticleCard({ article }: { article: Article }) {
return (
<article
className={clsx(
'overflow-hidden',
'p-5',
'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="flex items-center gap-2">
<span
className="size-2 rounded-full"
style={{ background: article.accent }}
/>
<p className="text-xs font-medium uppercase tracking-wide text-zinc-500 dark:text-zinc-400">
{article.section}
</p>
</div>
<h3 className="mt-4 text-base font-semibold leading-6">
{article.title}
</h3>
<p className="mt-3 text-sm leading-6 text-zinc-600 dark:text-zinc-400">
{article.excerpt}
</p>
<p className="mt-5 text-xs font-medium text-zinc-500 dark:text-zinc-400">
{article.readTime} read
</p>
</article>
);
}
export function ArticleGrid({ articles }: { articles: Article[] }) {
return (
<MasonryBalanced
items={articles}
columns={{ 0: 1, 640: 2 }}
gap={16}
estimatedItemHeight={220}
itemKey={(article) => article.id}
render={({ data }) => <ArticleCard article={data} />}
/>
);
}When to use
Use this for blogs, resource hubs, changelogs, case studies, and dashboard cards with optional sections.
Notes
- Pick an
estimatedItemHeightnear the average rendered card. - Use stable keys so measured heights follow the correct article.
- Use
minItemHeightif loading states can briefly measure too small.