PixelEqualHeightGrid

Grid wrapper that forces equal-height children via a 3-row subgrid (header / body / footer).

  • Inherits PixelGrid props (cols, gap, surface, etc.) minus align, which rowAlign sets
  • Gives each child grid-rows-[auto_1fr_auto] so footers align across the row
  • Surface-aware borders and transitions
  • rowAlign="top" keeps each item at its own height, at the top of its row
Status
stable
Category
layout
Since
v1.6.0

API

import { PixelEqualHeightGrid } from '@pxlkit/ui-kit';
PropTypeDefaultDescription
rowAlign'top' | 'stretch''stretch'stretch gives every item of a row the row's height; top keeps their own.
surface'pixel' | 'linear'—Surface override; defaults to the nearest provider.
cols1 | 2 | 3 | 4 | 5 | 6 | 12 | GridResponsiveColumns—Column count, or a count per breakpoint ({ base: 1, md: 3 }); ignored with autoFit / autoFill.
rows1 | 2 | 3 | 4 | 5 | 6—Row count.
gap0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16—Gap token (stackGap) between rows and columns.
askeyof React.JSX.IntrinsicElements—Element to render.
justify'start' | 'center' | 'end' | 'stretch'—Inline-axis alignment of the items.
colGap0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16—Gap between columns; with rowGap, it replaces gap.
rowGap0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12 | 16—Gap between rows; with colGap, it replaces gap.
autoFitboolean—As many columns as fit, empty tracks collapsed.
autoFillboolean—As many columns as fit, empty tracks kept.
minColWidthstring—Narrowest column with autoFit / autoFill (any CSS length).

Also takes the native attributes and event handlers of <div> (HTMLAttributes<HTMLDivElement>), except align.

ref points to <div>.

Accessibility

WCAG target: 2.1 AA

Inherits semantics from the underlying PixelGrid element (defaults to <div>). Use the as prop to render a more semantic container when appropriate.

Usage

import { cn, PixelEqualHeightGrid } from '@pxlkit/ui-kit';

function Card({ title, body, className }: { title: string; body: string; className?: string }) {
  return (
    <div className={cn('border border-retro-border p-4', className)}>
      <h3 className="text-sm font-semibold text-retro-text">{title}</h3>
      <p className="text-sm text-retro-muted">{body}</p>
      <div className="mt-2 text-xs text-retro-muted">Footer</div>
    </div>
  );
}

export function Default() {
  return (
    <PixelEqualHeightGrid cols={{ base: 1, sm: 3 }} gap={4}>
      <Card title="One" body="Short copy." />
      <Card title="Two" body="A longer body that forces the row to grow taller than the first card." />
      <Card title="Three" body="Medium length copy here." />
    </PixelEqualHeightGrid>
  );
}

Examples

Default

import { cn, PixelEqualHeightGrid } from '@pxlkit/ui-kit';

function Card({ title, body, className }: { title: string; body: string; className?: string }) {
  return (
    <div className={cn('border border-retro-border p-4', className)}>
      <h3 className="text-sm font-semibold text-retro-text">{title}</h3>
      <p className="text-sm text-retro-muted">{body}</p>
      <div className="mt-2 text-xs text-retro-muted">Footer</div>
    </div>
  );
}

export function Default() {
  return (
    <PixelEqualHeightGrid cols={{ base: 1, sm: 3 }} gap={4}>
      <Card title="One" body="Short copy." />
      <Card title="Two" body="A longer body that forces the row to grow taller than the first card." />
      <Card title="Three" body="Medium length copy here." />
    </PixelEqualHeightGrid>
  );
}

Row Align Top

import { cn, PixelEqualHeightGrid } from '@pxlkit/ui-kit';

function Card({ title, body, className }: { title: string; body: string; className?: string }) {
  return (
    <div className={cn('border border-retro-border p-4', className)}>
      <h3 className="text-sm font-semibold text-retro-text">{title}</h3>
      <p className="text-sm text-retro-muted">{body}</p>
      <div className="mt-2 text-xs text-retro-muted">Footer</div>
    </div>
  );
}

export function RowAlignTop() {
  return (
    <PixelEqualHeightGrid cols={{ base: 1, sm: 3 }} gap={4} rowAlign="top">
      <Card title="One" body="Short copy." />
      <Card title="Two" body="A longer body that would otherwise stretch siblings." />
      <Card title="Three" body="Medium length copy here." />
    </PixelEqualHeightGrid>
  );
}

Pixel Surface

import { cn, PixelEqualHeightGrid } from '@pxlkit/ui-kit';

function Card({ title, body, className }: { title: string; body: string; className?: string }) {
  return (
    <div className={cn('border border-retro-border p-4', className)}>
      <h3 className="text-sm font-semibold text-retro-text">{title}</h3>
      <p className="text-sm text-retro-muted">{body}</p>
      <div className="mt-2 text-xs text-retro-muted">Footer</div>
    </div>
  );
}

export function PixelSurface() {
  return (
    <PixelEqualHeightGrid cols={2} gap={4} surface="pixel">
      <Card title="Pixel A" body="Surface-aware grid item." />
      <Card title="Pixel B" body="Renders with the pixel surface tokens applied to the grid." />
    </PixelEqualHeightGrid>
  );
}

Related