v1.6.x-dev NDS IQ v6

Grid System - National Design System

A responsive CSS grid for arranging content into auto-fit or explicit column layouts, with per-breakpoint column counts, custom track templates, and adaptive gap scaling.

Basic Grid

The .nds-grid class creates a CSS grid that distributes children into equal columns. Use --max-col to set a fixed column count, or --min-width to set a minimum column width for automatic wrapping.

Fixed Column Count
1
2
3
4
5
6
<div class="nds-grid" style="--max-col: 3;"> <div class="nds-card nds-stroke">1</div> <div class="nds-card nds-stroke">2</div> <div class="nds-card nds-stroke">3</div> <div class="nds-card nds-stroke">4</div> <div class="nds-card nds-stroke">5</div> <div class="nds-card nds-stroke">6</div> </div>
Auto-fit with Min Width
1
2
3
4
5
6
<div class="nds-grid" style="--min-width: 200px;"> <div class="nds-card nds-stroke">1</div> <div class="nds-card nds-stroke">2</div> <div class="nds-card nds-stroke">3</div> <div class="nds-card nds-stroke">4</div> <div class="nds-card nds-stroke">5</div> <div class="nds-card nds-stroke">6</div> </div>

Custom Track Layouts

Use --max-track to define an explicit grid-template-columns value for asymmetric layouts like a sidebar next to a main column, or a mix of fixed and flexible tracks.

Asymmetric Tracks
Primary
Secondary
<div class="nds-grid" style="--max-track: 3fr 1fr; --mid-track: 2fr 1fr; --min-track: 1fr;"> <div class="nds-card nds-stroke">Primary</div> <div class="nds-card nds-stroke">Secondary</div> </div>
Collapse Auto-fit at Narrow Viewports
A
B
C
<!-- Auto-fit at large, forced single column at medium and below --> <div class="nds-grid" style="--mid-track: 1fr;"> <div class="nds-card nds-stroke">A</div> <div class="nds-card nds-stroke">B</div> <div class="nds-card nds-stroke">C</div> </div>

Responsive Auto-fit

Use --max-col, --mid-col, and --min-col to set column count per viewport. Each token cascades: --mid-col falls back to --max-col, and --min-col falls back to --mid-col then --max-col.

Auto-fit Responsive
A
B
C
D
<div class="nds-grid" style="--max-col: 4; --mid-col: 2; --min-col: 1;"> <div class="nds-card nds-stroke">A</div> <div class="nds-card nds-stroke">B</div> <div class="nds-card nds-stroke">C</div> <div class="nds-card nds-stroke">D</div> </div>

Responsive Breakpoints

The grid switches between --max-*, --mid-*, and --min-* tokens based on viewport width (standard media queries) by default. To make the grid respond to its container's width instead — useful for grids inside narrowed columns or sidebars — add the nds-cq utility to any ancestor. The grid then prefers the nearest nds-cq ancestor's width over the viewport. Gap values halve at the mid breakpoint.

Breakpoint Triggers
Active Token Viewport (media query) Container (inside .nds-cq) Fallback Chain
--max-col / --max-track 961px+ > 768px auto-fit
--mid-col / --mid-track 601px to 960px ≤ 768px --max-col → auto-fit
--min-col / --min-track ≤ 600px ≤ 480px --mid-col → --max-col → auto-fit

Customization Tokens

Override these CSS custom properties on .nds-grid to customize column count, track template, gap, and alignment.

Customization Examples
<!-- Custom gap and fixed column count --> <div class="nds-grid" style="--max-col: 3; --gap: var(--spacing-md); --row-gap: var(--spacing-xl);"> <div>...</div> <div>...</div> <div>...</div> </div> <!-- Minimum column width (auto-wraps when items can't fit at 250px) --> <div class="nds-grid" style="--min-width: 250px;"> <div>...</div> <div>...</div> <div>...</div> </div> <!-- Responsive: 4 cols large, 2 cols medium, 1 col small --> <div class="nds-grid" style="--max-col: 4; --mid-col: 2; --min-col: 1;"> <div>...</div> <div>...</div> </div> <!-- Explicit track template with responsive collapse --> <div class="nds-grid" style="--max-track: 3fr 1fr; --min-track: 1fr;"> <div>Primary</div> <div>Secondary</div> </div> <!-- Centered grid items --> <div class="nds-grid nds-center"> <div>...</div> </div>

Built-in Features

Auto-fit Columns

Grid children distribute into equal columns automatically, filling available width without manual column counts.

Minimum Width Wrapping

Set --min-width to wrap items naturally once they cannot fit the specified minimum, no media queries needed.

Responsive Column Tokens

Set different column counts with --max-col, --mid-col, and --min-col, triggered by viewport (or the nearest .nds-cq ancestor's width when opted in), each cascading to the next as a fallback.

Custom Track Layouts

Define explicit grid-template-columns per breakpoint with --max-track, --mid-track, and --min-track for asymmetric layouts.

Adaptive Gap Scaling

Gap and row-gap values halve automatically at the mid breakpoint (tablet viewport, or a 768px-wide .nds-cq ancestor), keeping spacing proportional in narrower contexts.

Alignment Tokens

Control horizontal and vertical alignment of grid items through --justify and --align custom properties.

Container-Aware (opt-in)

Add nds-cq to any ancestor (section wrapper, block, or custom element) to make the grid respond to that ancestor's width via CSS container queries — correct column counts inside sidebars or narrowed columns. Opt-in to avoid globally trapping position: fixed descendants.

Usage Guidelines

Best Practices

  • Use auto-fit mode (no column tokens) for uniform card grids, gallery layouts, and collections where items should wrap naturally into equal columns
  • Use responsive column tokens (--max-col, --mid-col, --min-col) when you want specific column counts per breakpoint rather than fluid wrapping
  • Use track tokens (--max-track, --mid-track, --min-track) for asymmetric layouts like sidebar + main content where columns need different widths
  • Set --mid-track: 1fr or --min-track: 1fr alone (without --max-track) to keep auto-fit behavior at large viewports while forcing a single-column stack below
  • Prefer --min-width over --max-col when the ideal column count depends on available space rather than a fixed number
  • Do not use the grid for single-column page flow. Standard block layout handles this without extra markup
  • Do not nest .nds-grid inside .nds-grid for complex page structures. Use Section to organize content into visual blocks
  • Always set --min-col or --min-track (commonly to 1 or 1fr) when using responsive tokens, so layouts collapse cleanly on narrow viewports
  • Override --gap with a spacing token when the default var(--spacing-2xl) is too wide for compact layouts like form fields or icon grids
  • Add nds-cq to a wrapper only when a nested grid sits inside a narrowed column and needs to respond to the column's width, not the viewport. Skip it for top-level grids that already span the page — viewport media queries handle those cleanly and avoid trapping fixed-position descendants in a new containing block

Modifier Classes

ClassDescription
nds-centerCenters grid items horizontally (sets --justify: center)

CSS Custom Properties

PropertyDefaultDescription
--max-colauto-fitColumn count at large viewport (961px+). Base value for the fallback chain
--mid-colvar(--max-col)Column count at medium viewport (601px to 960px)
--min-colvar(--mid-col)Column count below 601px
--max-track(unset)Explicit grid-template-columns value at large viewport. Overrides --max-col
--mid-trackvar(--max-track)Track template at medium viewport
--min-trackvar(--mid-track)Track template below 601px
--min-width0Minimum column width inside minmax() for auto-fit wrapping (e.g. 250px)
--gapvar(--spacing-2xl)Shorthand for both row and column gap. Halved automatically below the large breakpoint
--row-gapvar(--spacing-2xl)Row gap override
--col-gapvar(--spacing-2xl)Column gap override
--justifystretchHorizontal alignment of grid items (justify-items)
--alignstartVertical alignment of grid items (align-items)
Last Modified Date: 28/06/2026 - 01:27 PM
Was this page useful?
60% of users said Yes from 2843 Feedbacks