The Grid
Structural backbone: a .columns parent with only direct .column children. Put shared rhythm (counts, gaps, padding, surfaces) on the parent; keep cells for content. Add a single wckd-* root on that same parent when you opt into carousel, tabs, accordion, or filtering so wckd-ui.js sees a stable DOM.
Download & setup
Start with the package download and setup steps in Get Started, then use the style guide for utility and token references while implementing 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
Each block below is a standalone recipe. Pick the knobs that match your intent (density, gutters, height, spanning, surfaces), then add a wckd-* root on the same .columns element when interactivity is required.
Track density (count-*)
Use count-2 … count-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
count-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)
Comfortable (gap-l)
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.
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)
Child-level (intentional mix)
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)
Section B
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
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.
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
- Every page section: marketing bands, app settings rows, docs layouts, and dashboard tiles.
- Progressive handoff: ship static HTML first for layout sign-off, then add a single wckd-* class for behaviour without restructuring the Grid.
- Cross-team alignment: design and engineering share one vocabulary: count-*, gap-*, parent surfaces, optional wckd-* roots.
Implementation notes
- Treat .columns plus direct .column children as a DOM contract: many wckd-* initialisers walk immediate column children; extra wrapper divs between parent and .column can break measurements and focus management.
- Put shared chrome on the parent (padded-*, filled-*, rounded*, borders*) so you do not repeat the same utility stack on every child.
- When something does not carousel, tab, or accordion, validate root class and column shape before debugging JavaScript, most issues are markup drift.
- For carousels and sliders, avoid arbitrary margin on direct .column children; keep width math predictable for scroll-snap and track sizing.
- Use semantic elements inside cells (article, section, headings) freely, only the columns-to-column edge is constrained.
Developer checklist
- Parent is always .columns; direct children are always .column (or li.column when the columns container is a ul or ol).
- Load wckd-ui.css for grid utilities; load wckd-ui-components.css and wckd-ui.js when any variation uses wckd-* roots.
- After adding a wckd-* class, re-test keyboard focus, reduced motion (if applicable), and a narrow viewport where columns stack.
- Keep one interactive
wckd-*root per.columnselement; compose multiple Grids as siblings rather than nesting conflictingwckd-*parents unless a component explicitly documents nesting.