Grid
A CSS grid layout primitive that maps column counts, row counts, gap tokens, alignment, and flow options to concise props. Use it to build two-dimensional layouts ranging from simple card grids to complex asymmetric compositions.
Installation
npm install @designforge/uiUsage
import { Grid, gridVariants } from "@/components/ui/grid";Examples
Two Columns
import { Grid } from "@/components/ui/grid";
export function TwoColumns() {
return (
<Grid cols={2} gap="4">
<div className="rounded bg-muted p-6">Left</div>
<div className="rounded bg-muted p-6">Right</div>
</Grid>
);
}Three Columns
import { Grid } from "@/components/ui/grid";
export function ThreeColumns() {
return (
<Grid cols={3} gap="4">
<div className="rounded bg-muted p-4">Card 1</div>
<div className="rounded bg-muted p-4">Card 2</div>
<div className="rounded bg-muted p-4">Card 3</div>
<div className="rounded bg-muted p-4">Card 4</div>
<div className="rounded bg-muted p-4">Card 5</div>
<div className="rounded bg-muted p-4">Card 6</div>
</Grid>
);
}Four Columns
import { Grid } from "@/components/ui/grid";
export function FourColumns() {
return (
<Grid cols={4} gap="4">
{Array.from({ length: 8 }).map((_, i) => (
<div key={i} className="rounded bg-muted p-4 text-sm">
Item {i + 1}
</div>
))}
</Grid>
);
}Asymmetric Layout with colSpan
import { Grid } from "@/components/ui/grid";
export function AsymmetricLayout() {
return (
<Grid cols={3} gap="4">
{/* Sidebar spans 1 column, main content spans 2 */}
<div className="rounded bg-muted p-4">Sidebar</div>
<div className="col-span-2 rounded bg-muted p-4">Main Content</div>
{/* Full-width footer */}
<div className="col-span-3 rounded bg-muted p-4">Footer</div>
</Grid>
);
}Gap Variants
import { Grid } from "@/components/ui/grid";
const gaps = ["0", "1", "2", "4", "6", "8", "10", "12"] as const;
export function GapVariants() {
return (
<Grid cols={1} gap="6">
{gaps.map((gap) => (
<div key={gap}>
<p className="mb-1 text-xs text-muted-foreground">gap-{gap}</p>
<Grid cols={4} gap={gap}>
{[1, 2, 3, 4].map((n) => (
<div key={n} className="h-10 rounded bg-primary/30" />
))}
</Grid>
</div>
))}
</Grid>
);
}Auto-fill Pattern
import { Grid } from "@/components/ui/grid";
export function AutoFill() {
return (
/* Use flow="dense" so Tailwind fills empty holes automatically */
<Grid cols={4} gap="4" flow="dense">
<div className="col-span-2 rounded bg-primary/20 p-4">Wide</div>
<div className="rounded bg-muted p-4">A</div>
<div className="rounded bg-muted p-4">B</div>
<div className="rounded bg-muted p-4">C</div>
<div className="col-span-2 rounded bg-primary/20 p-4">Wide again</div>
<div className="rounded bg-muted p-4">D</div>
</Grid>
);
}Responsive Grid
import { Grid } from "@/components/ui/grid";
export function ResponsiveGrid() {
return (
/* Start with 1 col on mobile, override to 3 cols on md via className */
<Grid cols={1} gap="4" className="md:grid-cols-3">
{Array.from({ length: 6 }).map((_, i) => (
<div key={i} className="rounded bg-muted p-4 text-sm">
Item {i + 1}
</div>
))}
</Grid>
);
}Independent gapX and gapY
import { Grid } from "@/components/ui/grid";
export function IndependentGaps() {
return (
<Grid cols={3} gapX="8" gapY="2">
{Array.from({ length: 9 }).map((_, i) => (
<div key={i} className="rounded bg-muted p-4 text-sm text-center">
{i + 1}
</div>
))}
</Grid>
);
}API Reference
Grid
| Prop | Type | Default | Description |
|---|---|---|---|
cols | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | — | Number of explicit column tracks (grid-template-columns). |
rows | 1 | 2 | 3 | 4 | 5 | 6 | — | Number of explicit row tracks (grid-template-rows). |
gap | "0" | "1" | "2" | "3" | "4" | "5" | "6" | "8" | "10" | "12" | — | Uniform gap applied to both axes (gap). Overridden by gapX / gapY when those are set. |
gapX | "0" | "1" | "2" | "3" | "4" | "6" | "8" | — | Horizontal (column) gap only (column-gap). |
gapY | "0" | "1" | "2" | "3" | "4" | "6" | "8" | — | Vertical (row) gap only (row-gap). |
align | "start" | "center" | "end" | "stretch" | — | Aligns grid items along the block axis (align-items). |
justify | "start" | "center" | "end" | "stretch" | — | Aligns grid items along the inline axis (justify-items). |
flow | "row" | "col" | "dense" | "row-dense" | "col-dense" | — | Controls how auto-placed items flow into the grid (grid-auto-flow). |
className | string | — | Additional CSS classes merged onto the root element. |
ref | React.Ref<HTMLDivElement> | — | Forwarded ref to the underlying <div>. |
All other props are forwarded to the underlying <div> element.
gridVariants
gridVariants is the cva variant definition exported for composing Grid's class logic in custom components.
import { gridVariants } from "@/components/ui/grid";
const classes = gridVariants({ cols: 3, gap: "4", align: "start" });Accessibility
Gridrenders a plain<div>with no implicit ARIA role. Addrole="list"(withrole="listitem"children) or another appropriate role when the grid conveys a structured list of items.- Ensure the visual order of grid cells matches the DOM order so keyboard focus and screen-reader reading order remain logical — especially when using
flow="dense"which may place items visually out of sequence. - Do not use grid positioning alone to imply relationships between items; reinforce structure with headings, labels, or
aria-labelledby.