Skip to main content
BM

Grid

Responsive columns that fit their container, with no media queries.

View source on GitHub

  • Personal site

    Prerendered React on S3 and CloudFront.
  • Component library

    Accessible components built on design tokens.
  • Contact form

    A serverless API behind the site.
GridExample.tsx
import { Card } from "@/components/Card";
import { Grid } from "@/components/Grid";

const projects = [
  { name: "Personal site", summary: "Prerendered React on S3 and CloudFront." },
  { name: "Component library", summary: "Accessible components built on design tokens." },
  { name: "Contact form", summary: "A serverless API behind the site." },
];

export function GridExample() {
  return (
    <Grid as="ul" min="sm" maxColumns={3}>
      {projects.map(({ name, summary }) => (
        <Card key={name} as="li" heading={name} headingLevel={2}>
          {summary}
        </Card>
      ))}
    </Grid>
  );
}

Examples

min sm

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.
  • View counter

    Placeholder description.
  • Component library

    Placeholder description.

min md

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.
  • View counter

    Placeholder description.
  • Component library

    Placeholder description.

min lg

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.
  • View counter

    Placeholder description.
  • Component library

    Placeholder description.

Narrow container

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.

Row and column gaps

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.
  • View counter

    Placeholder description.
  • Component library

    Placeholder description.

Few items, stretched (default)

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.

Few items, stretch={false}

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.

At most two columns

  • Personal site

    Placeholder description.
  • Contact form

    Placeholder description.
  • View counter

    Placeholder description.
  • Component library

    Placeholder description.

Semantics

Projects to show

Props

Any native prop not listed here goes to the root element unchanged.

Items in a row are as tall as the tallest one, so Card edges line up. maxColumns is a ceiling, not a count: a container too narrow for that many min-wide columns shows fewer.

Grid props
PropTypeDefaultDescription
as"div" | "section" | "article" | "aside" | "header" | "footer" | "nav" | "main" | "ul" | "ol" | "li" | "form" | "fieldset""div"The root element. Lists keep their semantics without markers.
min"sm" | "md" | "lg""md"Minimum column width (size.column.*): 12, 16 or 20rem.
gap"none" | "xs" | "sm" | "md" | "lg" | "xl""md"Sets the row gap (space.stack.*) and the column gap (space.inline.*).
rowGap"none" | "xs" | "sm" | "md" | "lg" | "xl"gapBetween rows (space.stack.*).
columnGap"none" | "xs" | "sm" | "md" | "lg" | "xl"gapBetween columns (space.inline.*).
stretchbooleantrueWith room for more columns than items, items stretch to fill the row (auto-fit). false keeps the empty columns (auto-fill).
maxColumns2 | 3 | 4—At most this many columns. Columns still never get narrower than min, unless the container is.

Component tokens

None. Column minimums and gaps are chosen by props from semantic scales.

Accessibility

  • Same element set and list handling as Stack.
  • Narrower than one column, it shows a single full-width column with no horizontal scrolling.
  • Grid never reorders items (no dense packing), so reading and focus order follow the source.
  • As a fieldset, the legend still names the group and is spaced like the rows.