Density Tokens and Target Size in Data Grids

Permalink to "Density Tokens and Target Size in Data Grids"

Data grids need density options: analysts want 40 rows on screen, occasional users want room to breathe. Density is usually implemented by shrinking everything — padding, fonts, icons, checkboxes — until targets fall below what users with limited dexterity can hit, and rows clip text when users increase spacing. Design tokens let you define density precisely, separating what can shrink (visual padding) from what must not (hit areas, text size, spacing tolerance).

This guide belongs to design system tokens & component contracts.

Spec reference

Permalink to "Spec reference"
  • SC 2.5.8 Target Size (Minimum) (AA) — 24×24 CSS pixel targets or sufficient spacing.
  • SC 1.4.12 Text Spacing (AA) — rows must not clip text with increased spacing.
  • SC 1.4.4 Resize Text (AA) and SC 1.4.10 Reflow (AA) — density must work with zoom.
  • SC 2.5.5 Target Size (Enhanced) (AAA) — 44×44, a good goal for comfortable or touch densities.
Row height and minimum target by density Bar chart of row heights in pixels for comfortable 48, standard 40 and compact 32 densities, each with a minimum target of 24 pixels maintained through hit areas. Row height and minimum target by densityComfortabletarget 32 px; touch friendlyStandardtarget 24 pxCompacttarget 24 px via hit area; tight but compliantBelow minimumtargets 16 px — not offered
Row height shrinks; the target minimum does not.

When to use — and when not to

Permalink to "When to use — and when not to"

Use density tokens for any component with repeated rows and controls: grids, lists, tree views, menus. Offer two or three densities; more adds testing burden without benefit.

Do not define compact density by scaling fonts below the body size, or by reducing hit areas below 24 px. The misapplication: --row-height: 24px; --checkbox-size: 14px for “compact”, with height (not min-height) on rows.

Shrinking everything versus separating density from targets Comparison: shrinking everything produces tiny targets and clipped text; separating visual density from hit areas keeps compact layouts compliant. Shrinking everything versus separating density from targets✗ Shrink everythingCheckbox 14 px, hit area 14 pxFixed row height 24 pxFont 11 px in compactClips under text spacingFails 2.5.8 and 1.4.12✓ Separate density from targetsCheckbox 16 px visual, hit area 24 pxMinimum row height 32 px; grows with contentFont stays at body sizeGrows under text spacingPasses both

Annotated code example

Permalink to "Annotated code example"
{
  "density": {
    "standard":    { "rowMinHeight": "40px", "cellPaddingBlock": "8px", "cellPaddingInline": "12px", "iconSize": "20px", "targetMin": "24px" },
    "comfortable": { "rowMinHeight": "48px", "cellPaddingBlock": "12px", "cellPaddingInline": "16px", "iconSize": "20px", "targetMin": "32px" },
    "compact":     { "rowMinHeight": "32px", "cellPaddingBlock": "4px",  "cellPaddingInline": "8px",  "iconSize": "16px", "targetMin": "24px" }
  }
}
.grid { --row-min: var(--density-row-min-height); --pad-b: var(--density-cell-padding-block); --target: var(--density-target-min); }
.grid td, .grid th { min-block-size: var(--row-min); padding-block: var(--pad-b); line-height: 1.5; } /* min, not fixed (SC 1.4.12) */
.grid .cell-control {                                    /* every interactive control in a cell */
  min-inline-size: var(--target); min-block-size: var(--target);   /* hit area (SC 2.5.8) */
  display: inline-grid; place-items: center;
}
.grid .cell-control > svg { inline-size: var(--density-icon-size); block-size: var(--density-icon-size); }

Keyboard & AT behaviour

Permalink to "Keyboard & AT behaviour"

Density does not change semantics, but it affects focus visibility and readability:

Density Focus ring room Text size Notes
Comfortable Ample Body Best for touch and low vision
Standard Enough for 2–3 px outline Body Default
Compact Inset outline needed Body Use inset focus rings; test contrast
Density checks per WCAG criterion Matrix of densities — comfortable, standard, compact — against 2.5.8 target size, 1.4.12 text spacing, 1.4.10 reflow at 400 percent and focus visibility. Density checks per WCAG criterion2.5.81.4.121.4.10Focus visibleComfortablePassPassPassPassStandardPassPassPassPassCompactPass via hit areasPass with min heightsPassInset ring
Every offered density must pass every check.

Integration context

Permalink to "Integration context"

User-facing density controls are covered in segmented controls for view density. Testing is covered in testing target size 2.5.8 in dense grids and text spacing override testing for 1.4.12. Focus in compact rows relates to designing focus indicators for dense grids.

Gotchas

Permalink to "Gotchas"

Virtualization and row heights. Virtualizers that need fixed row heights conflict with min-height rows. Use dynamic measurement or reserve enough height for two lines at 1.5 line height.

Icons scaling with density. Icons can shrink visually; hit areas must not.

Third-party grids. Map your tokens onto library variables (AG Grid theme params, MUI density) and verify the library respects min heights.

Worked example

Permalink to "Worked example"

A design system’s compact density set rows to 28 px fixed and checkboxes to 14 px. Target-size tests flagged hundreds of controls, and text spacing tests clipped every second row. The team rewrote density tokens with a targetMin that never drops below 24 px, switched rows to minimum heights, and kept fonts at body size. Compact rows grew to 32 px; analysts still fit 30+ rows on screen, and the grid passed both tests in every density.

Common mistakes

Permalink to "Common mistakes"
  • Fixed row heights that clip under text spacing.
  • Shrinking fonts in compact density.
  • Margins mistaken for hit areas.
  • Untested densities added “for power users”.

Adoption checklist

Permalink to "Adoption checklist"
  1. Define density tokens with explicit targetMin values.
  2. Replace fixed heights with minimum heights across grid styles.
  3. Wrap interactive cell controls in hit-area containers sized from tokens.
  4. Add target-size and text-spacing tests per density to CI.
  5. Make standard density the default and persist user choices.
  6. Map tokens onto third-party grid theme parameters.

Worked numbers for a compact row

Permalink to "Worked numbers for a compact row"

A compact row with a 16-pixel checkbox illustrates the arithmetic. The visual checkbox stays 16 pixels; its label wrapper is 24×24, centred in the cell. With 4 pixels of vertical padding and a 1.5 line height at a 14-pixel font, text needs 21 pixels, so the row’s minimum height of 32 pixels leaves room for the 24-pixel target with 4 pixels above and below. Under text spacing overrides the line grows to about 21 pixels plus letter and word spacing, still within 32; if a cell wraps to two lines, the row simply grows to fit.

Testing checklist

Permalink to "Testing checklist"

Design system notes

Permalink to "Design system notes"

Publish density tokens with the WCAG checks they were verified against, and include a density switcher in component documentation so reviewers see every density.

FAQ

Permalink to "FAQ"
Can compact density be accessible?

Yes, if hit areas stay at 24 px and rows grow with content.

Should font size change with density?

Avoid shrinking below body size. Density should change spacing, not readability.

What default density should grids use?

Standard. Offer compact as an option for users who choose it.

How do I implement larger hit areas without changing visuals?

Wrap controls in elements sized to the target minimum, or use pseudo-elements to extend clickable areas.

Does density affect 1.4.10 reflow?

Indirectly: comfortable densities need more width; ensure tables still reflow or scroll appropriately at 400%.

Should touch devices default to comfortable?

Often yes; detect coarse pointers with media queries and let users override.

How many densities should we offer?

Two or three. Each must be tested.

How do density tokens interact with zoom?

Tokens in CSS pixels scale with browser zoom; that is expected. Ensure layouts reflow at 400% rather than overflowing.

Can density be adjusted per column?

Avoid it; mixed row heights confuse virtualization and readers. Adjust column widths instead.

Permalink to "Related"

← Back to Design System Tokens & Component Contracts