Components

The Grid

Page grid: .columns with only direct .column children. Put count-*, gaps, and surfaces on the parent. Optional .wckd-carousel, .wckd-tabs, etc. on that same parent when you need kit JS on the row.

Download & setup

Load the kit from Get Started; use the style guide for utilities and tokens while wiring this component.

Default implementation

The grid contract

Minimum viable grid: .columns sets the track model (count-*), .column elements are the only direct grid children, and parent utilities (gap, padded, filled, rounded) apply shared chrome in one place.

Column

Direct child of .columns.

Column

Same contract everywhere.

Column

Change count-* on the parent only.

Markup

<div class="columns count-3 gap padded filled rounded">
  <div class="column">…</div>
  <div class="column">…</div>
  <div class="column">…</div>
</div>

Configuration options

Recipes below: layout utilities on .columns, then add wckd-* on that same node only when you need JS.

Track density (count-*)

Use count-2count-6 (and related utilities from the style guide) on .columns to change how many tracks you get at a given breakpoint. Children stay .column; never insert anonymous wrappers between the parent and columns if a wckd-* module expects column children.

count-2

A
B

count-6

1
2
3
4
5
6

Markup

<div class="columns count-2 gap padded-s filled rounded text-center">…</div>
<div class="columns count-6 gap-s padded-s filled-light rounded text-center text-xs">…</div>

Gutters (gap, gap-*)

gap and gap-xs / gap-s / gap-m / gap-l control rhythm between columns. Tighten for dense dashboards; loosen for editorial hero rows.

Tight (gap-xs)

a
b
c

Comfortable (gap-l)

A
B
C

Markup

<div class="columns count-3 gap-xs padded filled-fade rounded">…</div>
<div class="columns count-3 gap-l padded-s filled-fade rounded text-center">…</div>

Equal-height columns (match-height)

Add match-height on .columns when cards or columns should stretch to the tallest sibling, common for pricing rows, feature tiles, or any row where uneven copy would break the visual baseline.

Short

Taller

Extra lines make this column taller without breaking the row rhythm when match-height is on the parent.

Medium

Still stretches.

Markup

<div class="columns count-3 gap match-height padded-s filled-light rounded">…</div>

Spanning tracks (span-*)

Use span-2 (and responsive variants like desktop-span-2 where documented) on a .column to widen one cell across multiple tracks, hero + sidebar, wide chart + meta column, etc.

Wide cell

span-2 across two tracks in a count-3 row.

Sidebar

Single track.

Full row item
Full row item
Full row item

Markup

<div class="columns count-3 gap padded-s filled rounded">
  <div class="column span-2">…</div>
  <div class="column">…</div>
</div>

Parent-level vs child-level utilities

Preferred: put padded-*, filled-*, rounded*, borders*, shadows on .columns when every child should share the same card chrome. Exception: use pad-*, fill-*, round* on individual .column cells when you deliberately need mixed surfaces (status lanes, contrast tiles, callouts).

Parent-level (preferred)

Same surface A
Same surface B
Same surface C

Child-level (intentional mix)

Light
Fade
Dark

Markup

<!-- Parent-level: chrome on .columns -->
<div class="columns count-3 gap padded filled-fade rounded">
  <div class="column">Same surface A</div>
  <div class="column">Same surface B</div>
  <div class="column">Same surface C</div>
</div>

<!-- Child-level (intentional mix): chrome on each .column -->
<div class="columns count-3 gap-s rounded">
  <div class="column pad-s fill-light border">Light</div>
  <div class="column pad-s fill-fade">Fade</div>
  <div class="column pad-s fill-dark">Dark</div>
</div>

Page rhythm (margin-* on wrappers)

Keep .columns focused on internal grid logic. Use outer wrappers (section, div) with margin-bottom-* / margin-top-* for vertical rhythm between sections so spacing stays predictable when grids stack on small viewports.

Section A (wrapper carries margin)

1
2
3

Section B

Left
Right

Markup

<section class="margin-bottom-xl">
  <div class="columns count-3 gap padded-s filled rounded">…</div>
</section>

Static grid → interactive carousel

Same markup shape as the carousel page: .wckd-carousel on the .columns parent; each slide is a .column. Needs wckd-ui.js (see Get Started). You can leave the class off while you check layout, then add it when you want arrows and dots. Arrows and dots are on by default; add hide-arrows / hide-dots, or hide-nav for both.

Static

A
B
C

Interactive (wckd-carousel)

Markup

<!-- static -->
<div class="columns count-1 gap padded-s filled-fade rounded">…</div>

<!-- interactive: add wckd-carousel on the same parent -->
<div class="wckd-carousel columns count-1 gap padded-s filled-fade rounded">…</div>

Accordion shell (wckd-accordion)

Each .column is one accordion row: button.accordion-toggle plus .accordion-content. Optional data-show-filter / data-show-expand-all on the parent add toolbar behaviour. Requires wckd-ui.js.

A .columns parent with direct .column children, shared utilities on the parent, semantics inside each cell.

Interactive modules query column children; changing wrappers breaks initialisers and keyboard flows.

Markup

<div class="wckd-accordion columns count-1 gap-s">
  <div class="column">
    <button type="button" class="accordion-toggle">Question</button>
    <div class="accordion-content">…</div>
  </div>
</div>

Tabs on the grid (wckd-tabs)

Each .column holds one tab: .tabs-toggle + .tabs-content. Mark the default panel with .column.active. The grid classes (columns, count-*, spacing) stay on the same element as .wckd-tabs. Requires wckd-ui.js.

High-level summary for this tab.

Copy the structure from each variation block.

Pair with Get Started for package + bootstrap wiring.

Markup

<div class="wckd-tabs columns count-1 accordion background-color">
  <div class="column active">
    <button type="button" class="tabs-toggle">Overview</button>
    <div class="tabs-content pad">…</div>
  </div>
  <div class="column">…</div>
</div>

Filterable list shell (wckd-list-filter)

Wrap .columns (or a ul.columns list) in .wckd-list-filter, add input.wckd-filter, and mark the list with .filterable. Each filterable item remains a .column (or li.column). Requires wckd-ui.js.

  • Billing
  • Identity
  • Analytics
  • Security
  • Support
  • Integrations

Markup

<div class="wckd-list-filter">
  <input class="wckd-filter" type="search" placeholder="Filter…" />
  <ul class="columns count-3 gap no-bullets filterable">
    <li class="column">…</li>
  </ul>
</div>

When to use

  • Page sections: marketing bands, settings rows, docs layouts, dashboards.
  • Ship static grid HTML first, then add one <code>wckd-*</code> class on that row for behaviour.

Implementation notes

  • .columns may only have direct .column children; extra wrappers break wckd-* measurement and focus.
  • Put shared chrome (padded-*, filled-*, rounded*) on the parent row, not on every cell.
  • Before debugging JS, confirm the wckd-* root sits on the same node as .columns and slides are not padded at the wrong level.
  • Use semantic elements inside cells; only the columns-to-column edge is constrained.

Developer checklist

  • Parent is .columns; children are .column (or li.column when the row is a list).
  • Load wckd-ui.css for the grid; add wckd-ui-components.css + wckd-ui.js when the row uses a wckd-* root.
  • After adding behaviour, re-test keyboard focus, reduced motion (if relevant), and one narrow viewport.
  • One wckd-* root per .columns; compose multiple grids as siblings unless docs say otherwise.

← All components