Add this component

npx zentauri-ui add grid

Accessibility notes

Keyboard accessible by default with semantic markup, visible focus treatment, and tokenized states. Add descriptive labels for icon-only or decorative usage.

Dependency notes

Check Installation for shared peers. This component keeps styling in Tailwind classes and the --zui-* token contract.

Layout

Flexible Grid for responsive layouts

Build dashboards, forms, and card collections with a CSS-driven Grid. Configure responsive layouts and item placement without measuring the viewport in JavaScript. Keep arbitrary React content and native controls inside neutral or styled items.

Revenue
Summary
Activity

Grid layout playground

Configure responsive columns, spacing, placement, and surfaces. Add or filter content while keeping React keys stable.

The width slider demonstrates intrinsic fit/fill behavior. Responsive presets follow the viewport. Below sm, items stack one per row by default; turn off Stack on mobile to use the configured layout at every width. Custom areas control the first three items, and fixed layouts clamp spans to the available columns from sm upward.

Live layout


Item 1
Item 2
Item 3
Item 4
Item 5
Item 6

Appearance gallery

Grid recipes

Auto-fitting semantic collection


  • Studio

    Flexible plans for your workspace.

  • Team

    Flexible plans for your workspace.

  • Enterprise

    Flexible plans for your workspace.

Responsive dashboard spans


Revenue
Summary
Activity

Named-area section


Account details
Account actions
Account history

Nested layouts, axis gaps, and native controls


Nested A
Nested B

Responsive and placement rules

Items stack one per row below the consumer's sm breakpoint by default (640px with standard Tailwind settings). Mobile stacking resets spans, starts, and named areas to preserve DOM order. Set stackOnMobile={false} on Grid to retain the configured mobile layout. Each nested Grid controls its own setting.

Responsive maps require base. From sm upward, missing breakpoints inherit the latest smaller entry; each layout replaces its whole descriptor. The consumer's Tailwind viewport breakpoints apply. Gap overrides resolve independently, and a rowGap or columnGap scalar remains active at every width.

Fixed numeric spans and starts clamp to declared columns. Auto layouts support span 1 or full, with automatic column placement. Named areas take precedence over spans; area="auto" clears them. Keep GridItem as a direct DOM grid child. Nested roots isolate their layout configuration.

Default items are neutral wrappers. Grid adds no ARIA grid roles, tab stops, or keyboard interception. Dense placement, explicit starts, and named areas can change visual order; keep meaningful DOM reading order. Use Bento Grid for expanding tiles and detail views. Animation, drag, resize, and persistence are follow-up features.

Grid API

Generated from the package prop types and variant definitions.

Grid

GridProps

Variants

PropTypeDefault
alignItems
centerendstartstretch
stretch
autoFlow
rowrow-dense
row
justifyItems
centerendstartstretch
stretch

Behavior

PropTypeDefault
as'div' | 'ol' | 'section' | 'ul' | undefinednone
autoRowsImplicit row sizing.Property.GridAutoRows<string | number> | undefined"auto"
columnGapOverrides gap on the column axis at every resolved breakpoint.GridResponsiveValue<GridGap> | undefinednone
gapToken spacing on both axes.GridResponsiveValue<GridGap> | undefined"md"
layoutComplete descriptors replace earlier layouts; omitted breakpoints inherit.GridResponsiveValue<GridLayout> | undefined{ mode: "fixed", columns: 1 }
rowGapOverrides gap on the row axis at every resolved breakpoint.GridResponsiveValue<GridGap> | undefinednone
stackOnMobileStack one item per row below the consumer's sm breakpoint, ignoring item placement. Set false to retain the configured mobile layout.boolean | undefinedtrue
Inherited HTML props
PropTypeDefault
childrenReactNodenone
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | MouseEventHandler<HTMLElement> | MouseEventHandler<HTMLOListElement> | MouseEventHandler<HTMLUListElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

GridItem

GridItemProps

Variants

PropTypeDefault
alignSelf
autocenterendstartstretch
none
appearance
bluecontrastcyandefaultemeraldglassgradient-bluegradient-greengradient-orangegradient-pinkgradient-purplegray+14
default
justifySelf
autocenterendstartstretch
none
padding
lgmdnonesm
none

Behavior

PropTypeDefault
areaNamed custom-layout area; auto clears an inherited area.GridResponsiveValue<string> | undefined"auto"
as'div' | 'article' | 'li' | undefinednone
colSpanFixed-layout spans clamp to available columns. Auto layouts support 1 or full.GridResponsiveValue<GridSpan> | undefined1
columnStartPositive line number; auto layouts use automatic placement.GridResponsiveValue<number | 'auto'> | undefined"auto"
rowSpanPositive integer span of implicit or explicit rows.GridResponsiveValue<number> | undefined1
rowStartPositive line number or automatic placement.GridResponsiveValue<number | 'auto'> | undefined"auto"
Inherited HTML props
PropTypeDefault
childrenReactNodenone
classNamestring | undefinednone
idstring | undefinednone
onClickMouseEventHandler<HTMLDivElement> | MouseEventHandler<HTMLElement> | MouseEventHandler<HTMLLIElement> | undefinednone
styleCSSProperties | undefinednone
titlestring | undefinednone

Installation and theme overrides

pnpm add @zentauri-ui/zentauri-components
# Or vendor the source:
pnpm dlx @zentauri-ui/zentauri-components add grid

The package ships utility strings. Add the package to Tailwind v4 scanning; the example path assumes an app/globals.css stylesheet at the project root. Adjust it for your stylesheet location. Vendored components must also be inside Tailwind's source scope.

@import "tailwindcss";
@source "../node_modules/@zentauri-ui/zentauri-components";

.my-grid-theme {
  --zui-grid-gap-md: 1.25rem;
  --zui-grid-gap-md-dark: 1.25rem;
  --zui-grid-blue-bg: #eff6ff;
  --zui-grid-blue-bg-dark: #172554;
}

Wrap Grid in the theme selector to inherit overrides. Consumer style is merged last: use style for advanced CSS templates or placement, with responsibility for valid CSS and mobile overflow.

CSS variable overrides

Grid CSS variables

Override Grid spacing and item surfaces on :root, a theme, or a wrapper. Private layout variables are not theme tokens.

190 variables

Pattern: --zui-<component>-<slot?>-<variant?>-<property>-<state?>-dark?

:root {
  --zui-grid-gap-xs: 0.25rem;
  --zui-grid-gap-sm: 0.5rem;
  --zui-grid-gap-md: 1rem;
  --zui-grid-gap-lg: 1.5rem;
  --zui-grid-gap-xl: 2rem;
  --zui-grid-min-item-width: 16rem;
  --zui-grid-item-padding-sm: 0.5rem;
  --zui-grid-item-padding-md: 1rem;
  --zui-grid-item-padding-lg: 1.5rem;
  --zui-grid-item-radius: 0.75rem;
  --zui-grid-item-border-width: 1px;
  --zui-grid-default-bg: transparent;
  --zui-grid-default-fg: inherit;
  --zui-grid-default-border: transparent;
  --zui-grid-subtle-bg: #f8fafc;
  --zui-grid-subtle-fg: #334155;
  --zui-grid-subtle-border: #e2e8f0;
  --zui-grid-contrast-bg: #0f172a;
  --zui-grid-contrast-fg: #f8fafc;
  --zui-grid-contrast-border: #334155;
  --zui-grid-glass-blur: 12px;
  --zui-grid-glass-bg: #ffffffb3;
  --zui-grid-glass-fg: #0f172a;
  --zui-grid-glass-border: #cbd5e1;
  --zui-grid-blue-bg: #eff6ff;
  --zui-grid-blue-fg: #1e40af;
  --zui-grid-blue-border: #bfdbfe;
  --zui-grid-cyan-bg: #ecfeff;
  --zui-grid-cyan-fg: #155e75;
  --zui-grid-cyan-border: #a5f3fc;
  --zui-grid-green-bg: #f0fdf4;
  --zui-grid-green-fg: #166534;
  --zui-grid-green-border: #bbf7d0;
  --zui-grid-lime-bg: #f7fee7;
  --zui-grid-lime-fg: #3f6212;
  --zui-grid-lime-border: #d9f99d;
  --zui-grid-emerald-bg: #ecfdf5;
  --zui-grid-emerald-fg: #065f46;
  --zui-grid-emerald-border: #a7f3d0;
  --zui-grid-indigo-bg: #eef2ff;
  --zui-grid-indigo-fg: #3730a3;
  --zui-grid-indigo-border: #c7d2fe;
  --zui-grid-purple-bg: #faf5ff;
  --zui-grid-purple-fg: #6b21a8;
  --zui-grid-purple-border: #e9d5ff;
  --zui-grid-pink-bg: #fdf2f8;
  --zui-grid-pink-fg: #9d174d;
  --zui-grid-pink-border: #fbcfe8;
  --zui-grid-rose-bg: #fff1f2;
  --zui-grid-rose-fg: #9f1239;
  --zui-grid-rose-border: #fecdd3;
  --zui-grid-sky-bg: #f0f9ff;
  --zui-grid-sky-fg: #075985;
  --zui-grid-sky-border: #bae6fd;
  --zui-grid-teal-bg: #f0fdfa;
  --zui-grid-teal-fg: #115e59;
  --zui-grid-teal-border: #99f6e4;
  --zui-grid-yellow-bg: #fefce8;
  --zui-grid-yellow-fg: #854d0e;
  --zui-grid-yellow-border: #fef08a;
  --zui-grid-orange-bg: #fff7ed;
  --zui-grid-orange-fg: #9a3412;
  --zui-grid-orange-border: #fed7aa;
  --zui-grid-red-bg: #fef2f2;
  --zui-grid-red-fg: #991b1b;
  --zui-grid-red-border: #fecaca;
  --zui-grid-slate-bg: #f8fafc;
  --zui-grid-slate-fg: #334155;
  --zui-grid-slate-border: #cbd5e1;
  --zui-grid-gray-bg: #f9fafb;
  --zui-grid-gray-fg: #374151;
  --zui-grid-gray-border: #d1d5db;
  --zui-grid-zinc-bg: #fafafa;
  --zui-grid-zinc-fg: #3f3f46;
  --zui-grid-zinc-border: #d4d4d8;
  --zui-grid-gradient-blue-from: #eff6ff;
  --zui-grid-gradient-blue-to: #faf5ff;
  --zui-grid-gradient-blue-fg: #0f172a;
  --zui-grid-gradient-blue-border: #bfdbfe;
  --zui-grid-gradient-green-from: #f0fdf4;
  --zui-grid-gradient-green-to: #f7fee7;
  --zui-grid-gradient-green-fg: #0f172a;
  --zui-grid-gradient-green-border: #bbf7d0;
  --zui-grid-gradient-purple-from: #faf5ff;
  --zui-grid-gradient-purple-to: #fdf2f8;
  --zui-grid-gradient-purple-fg: #0f172a;
  --zui-grid-gradient-purple-border: #e9d5ff;
  --zui-grid-gradient-orange-from: #fff7ed;
  --zui-grid-gradient-orange-to: #fefce8;
  --zui-grid-gradient-orange-fg: #0f172a;
  --zui-grid-gradient-orange-border: #fed7aa;
  --zui-grid-gradient-pink-from: #fdf2f8;
  --zui-grid-gradient-pink-to: #fff1f2;
  --zui-grid-gradient-pink-fg: #0f172a;
  --zui-grid-gradient-pink-border: #fbcfe8;
}

/* Dark theme variables follow the same names with -dark appended. */
.dark {
  --zui-grid-gap-xs-dark: 0.25rem;
  --zui-grid-gap-sm-dark: 0.5rem;
  /* ...same variables with -dark at the end */
}

What it does

Grid supports fixed columns, auto-fit/auto-fill layouts, and custom templates with named areas. GridItem supports responsive spans and starts, optional surfaces, padding, and self-alignment. Native props and refs are retained.

Common use cases

  • Responsive dashboards with mobile-safe spans.
  • Card collections that fit their available container width.
  • Forms and account sections with named areas.
  • Nested layouts with shared spacing and appearance tokens.

Accessibility

Use Grid as a list with li items or a labeled section when appropriate. Grid does not add focus stops or intercept child keyboard events. Dense flow and explicit placement are opt-in; keep DOM order meaningful for keyboard and screen-reader users.

FAQ

What makes Grid dynamic?

CSS responds to available space and viewport breakpoint variants. Consumers filter, sort, insert, or remove keyed children with normal React state; Grid does not maintain a separate data model.

How does Grid differ from Bento Grid or DataTable?

Grid provides neutral responsive layout and placement. Bento Grid adds styled feature tiles, expansion, and detail interactions. DataTable provides tabular record behavior such as sorting and selection.

Does Grid require Framer Motion?

No. The static grid entry has no animation dependency. Reflow animation, drag, resize, and persistence are not part of this initial release.

Are breakpoints based on the viewport or the container?

Responsive maps use the consumer's Tailwind viewport breakpoints. Auto-fit and auto-fill layouts size columns to the available parent width without breakpoint maps or JavaScript observers.

How do auto-fit and auto-fill differ?

Auto-fit collapses empty repeated tracks, letting occupied tracks grow. Auto-fill retains empty tracks. Auto layouts support ordinary span-1 items and full-width items; wider numeric spans and explicit column starts normalize to ordinary placement.

How do item spans behave on mobile?

By default, items stack one per row below the consumer's sm breakpoint, resetting spans, starts, and named areas. Set stackOnMobile={false} to retain the configured mobile layout. From sm upward, the declared layout and placement resume. Consumer style overrides take precedence.

Does CSS Grid require role=grid?

No. This is a layout component, not an interactive ARIA grid widget. Native list or section semantics and child controls remain available. Explicit placement, dense flow, and named areas can change visual order; keep a meaningful DOM reading sequence.

How do I configure Tailwind scanning?

Add an @source path to the installed component package relative to your stylesheet. If you vendor Grid through the CLI, include the resulting source folder in Tailwind's scan scope.