Grid

CSS grid container with column and gap utilities using design tokens.

import { ... } from '@corndev/ui'
Column 1
Column 2
Column 3
Col 1
Col 2
Col 3
Col 4
Large row gap
Small col gap
Row 2 A
Row 2 B

HTML

No JavaScript required — these classes are the whole component.

<div class="corn-grid" data-cols data-gap="md" style="--corn-grid-cols: 3">
  <div>Column 1</div>
  <div>Column 2</div>
  <div>Column 3</div>
</div>

<!-- Uneven spans, and a column as wide as its contents beside one taking the rest. -->
<div class="corn-grid" data-gap="md">
  <div class="corn-grid-col" data-span="4">Location</div>
  <div class="corn-grid-col" data-span="8">Name</div>
  <div class="corn-grid-col" data-span="content"><select aria-label="Type"><option>string</option></select></div>
  <div class="corn-grid-col" data-span="auto">Format</div>
</div>

Classes

Class
.corn-grid
.corn-grid-col

Attributes

OnAttributeValues
.corn-griddata-colspresent or absent
.corn-griddata-gapxs|sm|md|lg|xl
.corn-griddata-row-gapxs|sm|md|lg|xl
.corn-griddata-col-gapxs|sm|md|lg|xl
.corn-grid-coldata-span1|2|3|4|5|6|7|8|9|10|11|12|content|auto

CSS variables

VariableDefaultDescription
--corn-grid-cols12Column count when data-cols is set

Vanilla JS

Optional. createGrid only adds and removes the classes and attributes above, so the HTML is equivalent. Reach for it when you need to change options at runtime.

import { createGrid } from '@corndev/ui';
import '@corndev/ui/theme';

const el = document.querySelector('#target');
const instance = createGrid(el, { /* options */ });

Options

OptionTypeDefaultDescription
colsnumber|null12Equal columns, written to the --corn-grid-cols custom property. Pass null for no column template, so you can set grid-template-columns or grid-template-areas yourself.
gap'xs'|'sm'|'md'|'lg'|'xl'|null'md'Uniform gap between cells.
rowGap'xs'|'sm'|'md'|'lg'|'xl'undefinedRow gap only; overrides the uniform gap.
colGap'xs'|'sm'|'md'|'lg'|'xl'undefinedColumn gap only; overrides the uniform gap.

React

Grid, GridCol — from @corndev/ui-react.

The props are the same as the options above, plus className.

<Grid.Col> props

A cell that says how much of the row it takes.

PropTypeDefaultDescription
spannumber|'content'|'auto'12How much of the row to take.
childrenReact.ReactNodeundefined
classNamestringundefined
styleReact.CSSPropertiesundefined

Basic usage

Apply .corn-grid to any container to make it a CSS grid. Use data-cols with the --corn-grid-cols custom property to define equal-width columns.

import '@corndev/ui/theme';

<div class="corn-grid" data-cols data-gap="md" style="--corn-grid-cols: 3">
  <div>Column 1</div>
  <div>Column 2</div>
  <div>Column 3</div>
</div>

Column count

Set --corn-grid-cols inline to control how many equal columns the grid has.

<!-- 2 columns -->
<div class="corn-grid" data-cols style="--corn-grid-cols: 2">...</div>

<!-- 4 columns -->
<div class="corn-grid" data-cols style="--corn-grid-cols: 4">...</div>

<!-- 12-column layout grid -->
<div class="corn-grid" data-cols style="--corn-grid-cols: 12">...</div>

Without --corn-grid-cols, use native grid-template-columns inline or in your own stylesheet for non-uniform layouts. From the controller or the React component, that is cols: null:

createGrid(el, { cols: null, gap: 'md' });
<Grid cols={null} gap="md" style={{ gridTemplateAreas: '"nav main"' }}>…</Grid>

An invalid count — zero, negative, fractional — falls back to the stylesheet’s default of 12 rather than emitting repeat(0, …), which would void grid-template-columns entirely and collapse the layout to a single column.

Gap sizes

<div class="corn-grid" data-cols data-gap="xs" style="--corn-grid-cols: 2">...</div>
<div class="corn-grid" data-cols data-gap="sm" style="--corn-grid-cols: 2">...</div>
<div class="corn-grid" data-cols data-gap="md" style="--corn-grid-cols: 2">...</div>
<div class="corn-grid" data-cols data-gap="lg" style="--corn-grid-cols: 2">...</div>
<div class="corn-grid" data-cols data-gap="xl" style="--corn-grid-cols: 2">...</div>

Row and column gap overrides

Override just the row or column gap independently.

<!-- Large row gap, small column gap -->
<div
  class="corn-grid" data-cols data-row-gap="lg" data-col-gap="sm"
  style="--corn-grid-cols: 3"
>
  ...
</div>

Uneven columns

Grid.Col says how much of the row a child takes. A form row is rarely an even split — a parameter’s location beside its name, a type beside its format, then a full-width row beneath:

<Grid>
  <Grid.Col span={4}><Select aria-label="In" … /></Grid.Col>
  <Grid.Col span={8}><Input aria-label="Name" /></Grid.Col>
  <Grid.Col span={12}><Textarea aria-label="Description" autosize /></Grid.Col>
</Grid>

A number spans that many of cols (12 by default), and the gaps are accounted for, so 6 + 6 and 4 + 8 fill the row exactly.

content and auto

<Grid>
  <Grid.Col span="content"><Select aria-label="Type" … /></Grid.Col>
  <Grid.Col span="auto"><Input aria-label="Format" /></Grid.Col>
</Grid>

content is as wide as what is inside it — a small select sitting snugly beside a field instead of taking half the row. auto takes whatever the row has left. Neither can be expressed with fixed tracks, so a grid holding columns lays out as a wrapping flex row; a child that is not a column still renders, at its own width.

On a narrow screen — below 640px — every column takes the full row, so a desktop split never survives onto a phone.

Without React it is the class and an attribute:

<div class="corn-grid" data-gap="md">
  <div class="corn-grid-col" data-span="4">…</div>
  <div class="corn-grid-col" data-span="8">…</div>
</div>