Responsive Grid
A content-agnostic responsive grid container. CSS Grid tracks are sized via the auto-fit + minmax pattern, so the grid reflows without media queries. Pair it with any card, image, or tile component to get a responsive surface.
01
02
03
04
05
06
07
08
09
Customize
Items
9
Layout
10rem
3
Shape
Installation
npx shadcn@latest add https://craftbits.dev/r/responsive-grid.jsonUsage
import { ResponsiveGrid } from "@craft-bits/core";
<ResponsiveGrid minColumnWidth="16rem" gap={4}>
{items.map((item) => (
<Card key={item.id} {...item} />
))}
</ResponsiveGrid>Lock every item to a square so the layout reads as a uniform mosaic:
<ResponsiveGrid minColumnWidth="12rem" gap={3} aspectRatio="1">
{images.map((image) => (
<img key={image.id} src={image.src} alt={image.alt} />
))}
</ResponsiveGrid>Understanding the component
- Pure layout. The component only owns the wrapping div's grid template and gap. Children render verbatim as direct grid items.
- Responsive without media queries. Tracks use the auto-fit minmax pattern; as the viewport shrinks, tracks collapse and items reflow.
- Aspect ratio is opt-in. Pass an
aspectRatiostring and every immediate child receives that ratio via a CSS variable, so the grid reads as a uniform tile field. Omit it and items size to their own content. - No hidden image handling. Unlike the source, this grid is content-agnostic. Use any component as a child.
Variants
Three tight columns with generous gap:
<ResponsiveGrid minColumnWidth="14rem" gap="1.25rem">
{children}
</ResponsiveGrid>Square tiles for a gallery surface:
<ResponsiveGrid minColumnWidth="10rem" gap={3} aspectRatio="1">
{children}
</ResponsiveGrid>Wide cinematic tiles:
<ResponsiveGrid minColumnWidth="18rem" gap={4} aspectRatio="16/9">
{children}
</ResponsiveGrid>Props
| Prop | Type | Default | Description |
|---|---|---|---|
minColumnWidth | string | '16rem' | Floor width for each auto-fit track. Accepts any CSS length. |
gap | number | string | 4 | Numbers map to Tailwind spacing units (4 = 1rem); strings are used verbatim. |
aspectRatio | string | — | Optional CSS aspect-ratio applied to every immediate child (e.g. '1', '16/9'). |
className | string | — | Merged onto the grid root via cn(). |
Accessibility
- The grid is a plain
<div>by default. When the items form a semantic list, pairrole="list"on the root withrole="listitem"on each child so assistive tech announces the relationship. - Focus order follows DOM order. Items render in array order, so reorder children to reorder tab focus.
- The component never animates layout, so no reduced-motion fallback is required.
Credits
- Extracted from:
terminal-dreams(src/components/frontend-design/sdp-image-gallery/ui/ResponsiveGrid.tsx). The source coupled the grid to a project-specificGalleryImagetype, lightbox callbacks, retry / placeholder / lazy-load state, and an embedded Picsum image renderer. craft-bits keeps the responsive auto-fit layout but reshapes the API to a content-agnostic container that accepts arbitrary children, exposesminColumnWidth/gap/aspectRatio, and strips every image-specific concern.