Grid
A CSS-grid layout primitive with static and responsive column counts, gap presets, flow control, and per-cell placement via GridItem. Polymorphic render, RTL, and no hard-coded tokens.
Playground
Installation
pnpm add @tessinaui/uiUsage
import { Grid, GridItem } from "@tessinaui/ui";{/* Fixed 3-column grid */}
<Grid cols={3} gap="md">
<Card>One</Card>
<Card>Two</Card>
<Card>Three</Card>
</Grid>
{/* Responsive columns */}
<Grid cols={{ base: 1, sm: 2, md: 3, lg: 4 }} gap="sm">
{items.map((item) => <Card key={item.id}>{item.title}</Card>)}
</Grid>
{/* Cell placement with GridItem */}
<Grid cols={4} rows={3} gap="sm">
<GridItem colSpan={2} rowSpan={2}>
<Card>Featured</Card>
</GridItem>
<Card>1</Card>
<Card>2</Card>
<Card>3</Card>
<Card>4</Card>
</Grid>
{/* Explicit line placement */}
<Grid cols={6}>
<GridItem colStart={2} colEnd={5}>
<Hero />
</GridItem>
</Grid>
{/* Dense flow backfills gaps */}
<Grid cols={4} flow="dense" gap="sm">
<GridItem colSpan={2}>Wide</GridItem>
<Card>Auto</Card>
<Card>Auto</Card>
</Grid>Showcase
Columns
Pass a number for a fixed count, or a breakpoint object for responsive layouts.
<Grid cols={3}>…</Grid>
<Grid cols={{ base: 1, sm: 2, md: 3, lg: 4, xl: 6 }}>…</Grid>Supported column counts: 1 through 12.
Supported breakpoints: base, sm, md, lg, xl.
Rows
| Value | CSS mapping |
|---|---|
1–6 | grid-rows-1 – grid-rows-6 |
Explicit row counts are usually only needed when using rowSpan or rowStart/rowEnd.
Gap
Seven presets that map to Tailwind's spacing scale.
| Value | Tailwind | px |
|---|---|---|
"none" | gap-0 | 0 |
"xs" | gap-1 | 4 |
"sm" | gap-2 | 8 |
"md" (default) | gap-4 | 16 |
"lg" | gap-6 | 24 |
"xl" | gap-8 | 32 |
"2xl" | gap-12 | 48 |
For independent axis control use rowGap and columnGap — they accept the same seven values and override gap on their respective axis.
Flow
Controls how auto-placed items fill the grid.
| Value | CSS mapping |
|---|---|
"row" | grid-flow-row — fill row by row (default) |
"col" | grid-flow-col — fill column by column |
"dense" | grid-flow-dense — backfill gaps with smaller items |
"row-dense" | grid-flow-row-dense |
"col-dense" | grid-flow-col-dense |
Alignment
| Prop | CSS | Values |
|---|---|---|
alignItems | align-items | start / center / end / stretch / baseline |
justifyItems | justify-items | start / center / end / stretch |
alignContent | align-content | start / center / end / stretch |
justifyContent | justify-content | start / center / end / stretch |
Inline
inline={true} swaps grid for inline-grid so the container flows alongside surrounding inline content.
Polymorphic render
Clone a semantic element while keeping Grid styling.
<Grid render={<ul aria-label="Tiles" />} cols={3} gap="md">
<li>One</li>
<li>Two</li>
<li>Three</li>
</Grid>GridItem
Per-cell placement and alignment helpers. GridItem is optional — you can always apply col-span-* / row-span-* directly with className.
colSpan / rowSpan
| Value | CSS |
|---|---|
"auto" | col-auto / row-auto |
"full" | col-span-full / row-span-full |
1–12 | col-span-n / row-span-n (row max 6) |
colStart / colEnd / rowStart / rowEnd
Explicit grid-line placement. Start values accept "auto" or 1–13. End values accept "auto" or 1–13.
<GridItem colStart={2} colEnd={5}>…</GridItem>alignSelf / justifySelf
Per-cell override of the parent's alignItems / justifyItems.
<GridItem alignSelf="end" justifySelf="center">…</GridItem>RTL
dir="rtl" is forwarded to the DOM node. In RTL, columns are laid out right-to-left, mirroring the logical column order.
Accessibility
- Grid is a structural primitive — it applies no ARIA roles.
- Use
renderto mount semantic HTML (<ul>,<section>,<main>) when the grouping has meaning. - Reordering via
colStart/rowStartseparates visual order from DOM order. Keep DOM order logical — screen readers and keyboard navigation follow source order, not visual order.
When to use Grid vs. Flex
| Use Grid when… | Use Flex when… |
|---|---|
| You have a two-dimensional layout | You have a one-dimensional layout |
| Items should align on both axes | Only the main axis matters |
| You need equal-width columns without basis math | Item widths vary by content |
You want explicit cell placement (colStart, rowSpan) | Items flow naturally |
API Reference
Grid Props
| Prop | Type | Default | Description |
|---|---|---|---|
cols | 1..12 or { base, sm, md, lg, xl } | — | Column count (fixed or responsive) |
rows | 1..6 | — | Row count |
gap | "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "md" | Both-axis gap |
rowGap | Same as gap | — | Vertical gap (overrides gap) |
columnGap | Same as gap | — | Horizontal gap (overrides gap) |
flow | "row" | "col" | "dense" | "row-dense" | "col-dense" | — | grid-auto-flow |
alignItems | "start" | "center" | "end" | "stretch" | "baseline" | — | align-items |
justifyItems | "start" | "center" | "end" | "stretch" | — | justify-items |
alignContent | "start" | "center" | "end" | "stretch" | — | align-content |
justifyContent | "start" | "center" | "end" | "stretch" | — | justify-content |
inline | boolean | false | Use inline-grid |
render | ReactElement | — | Polymorphic target |
dir | "ltr" | "rtl" | — | Text direction |
className | string | — | Extra classes |
GridItem Props
| Prop | Type | Default | Description |
|---|---|---|---|
colSpan | "auto" | "full" | 1..12 | — | grid-column: span n |
rowSpan | "auto" | "full" | 1..12 | — | grid-row: span n |
colStart | "auto" | 1..13 | — | grid-column-start |
colEnd | "auto" | 1..13 | — | grid-column-end |
rowStart | "auto" | 1..13 | — | grid-row-start |
rowEnd | "auto" | 1..13 | — | grid-row-end |
alignSelf | "auto" | "start" | "center" | "end" | "stretch" | "baseline" | — | align-self |
justifySelf | "auto" | "start" | "center" | "end" | "stretch" | — | justify-self |
render | ReactElement | — | Polymorphic target |
dir | "ltr" | "rtl" | — | Text direction |
className | string | — | Extra classes |
Notes
- No intrinsic padding. Grid only controls layout — add padding, borders, background via
className. - No SSR caveats. Grid is a pure wrapper with no hooks; safe to render server-side.
- Static class names. All CSS class names are resolved at compile time — Tailwind's JIT sees them.
- Arbitrary values. If you need something outside the presets (e.g.
cols={18},gap="7"), drop toclassName="grid-cols-[18] gap-[28px]".
Flex
A low-level flexbox layout primitive that exposes the full flex API — four directions, three wrap modes, independent row and column gap, align-items, justify-content, align-content, inline mode, polymorphic render, and LTR/RTL. Ships with FlexItem for per-child grow, shrink, basis, order, and alignSelf control.
AspectRatio
Constrains content to a specific width/height ratio using CSS aspect-ratio. Seven named presets, arbitrary string or numeric ratios, eight corner-radius presets, automatic object-fit on single media children, and polymorphic render.