Skip to content
RU
Scale
Density
Theme
Accent

Foundations

Density

Density is an attribute of a container. One attribute on a panel retunes everything inside it: the tier of roles changes, and the components hold no numbers of their own.

Density moves geometry and does not touch type size: in all three modes the text stays 14px, and what changes is the air around it. Size is the business of the second axis — scale — and the axes add up.

The component
done
Markup
<div class="inst-cluster" data-density="compact">
  <button class="inst-btn inst-btn--sm" type="button">sm</button>
  <button class="inst-btn" type="button">md</button>
  <span class="inst-badge" data-tone="ok"><span class="inst-dot"></span>done</span>
  <input class="inst-input inst-input--sm" type="text" value="compact">
</div>

Contract

<section data-density="compact">
  <!-- everything inside is retuned -->
</section>

The attribute is inherited through the cascade of custom properties, so it works at any depth and on any container. Nesting is allowed: an inner region with a different value overrides the outer one.

Value What for
no attribute The default. A panel tool, a dashboard, most screens
data-density="compact" A dense tabular view: an agent queue, a log, a tree, a property inspector
data-density="comfortable" Forms, settings, wizards — where there are few decisions and each wants attention. Also a conversation: a chat is read rather than scanned, and the taller control is the one that matches it

Accessibility

Tap targets

WCAG 2.5.8 (AA) asks for a tap target no smaller than 24×24 CSS pixels. At density compact a control of size sm gives 22px — below the threshold. That is a deliberate trade: a dense tabular view exists for the sake of density.

Density --control-h-sm --control-h-md The 24px threshold
compact 22px 26px sm does not pass
default 26px 32px Passes
comfortable 30px 36px Passes

The rule of application: compact is for dense tabular views, not for the main navigation and not for the principal actions of a screen. If a user hits this control with a mouse every day, it must not be 22px. The WCAG exception for targets that have an equivalent of a normal size applies only when such an equivalent really exists.

Everything else

Type size It does not shrink at any density: the floor of 11px stays the floor
Contrast It does not depend on density — the same pairs are checked once
Text zoom The heights are applied as min-block-size, so an increased browser font stretches a control rather than cutting it off. True at all three densities
Keyboard Density changes neither the order of traversal nor the targets it hides: it is pure geometry

Scale

Exactly the tier of roles, and that is enough.

Control heights and paddings

Token compact default comfortable
--control-h-xs 18px 20px 22px
--control-h-sm 22px 24px 28px
--control-h-md 26px 32px 36px
--control-h-lg 32px 38px 44px
--control-pad-sm --space-3 --space-4 --space-5
--control-pad-md --space-4 --space-5 --space-6
--control-pad-lg --space-5 --space-6 --space-7

Region paddings

Token compact default comfortable
--pad-panel --space-4 --space-5 --space-6
--pad-card --space-5 --space-6 --space-7
--pad-cell-x --space-3 --space-4 --space-5
--row-pad-y --space-2 --space-3 --space-4
--gap-row --space-2 --space-3 --space-4
--gap-inline --space-3 --space-4 --space-5

Glyphs and gutters

Token compact default comfortable
--size-check 13px 15px 17px
--size-switch-w 26px 30px 34px
--size-switch-h 15px 18px 20px
--size-thumb 12px 14px 16px
--size-spinner 13px 14px 16px
--size-gutter 12px 14px 16px
--size-indent 12px 14px 16px

What is NOT retuned

What Why
Type size Density is about geometry. Shrinking the text along with the paddings means hitting the 11px floor within one step. Type size is moved by scale — the second axis, which adds up with this one
Colour and contrast The thresholds do not depend on how many rows fit on a screen
Radii The shape of an object does not change with how tightly it stands
--size-dot, --size-marker, --size-icon Carriers of meaning. A dot at 4px does not read, a mark at 1px is not seen
--space-* The scale is the foundation. Density moves the roles, not the scale under them

Behavior

The tier of roles is declared at zero specificity: a default with the same specificity as an override stops being a default.

So an application overrides any role without a fight — including those density does not retune:

.my-inspector { --label-col: 120px; }

Rules

A component that breaks at compact holds a hard-coded constant that ought to be a role. Three densities are an obligatory run when a component is added, on a par with the contrast check.

What to take and what not to

Use Take instead
compact for a dense tabular view: a queue, a log, an inspector compact for the main navigation — the tap targets go below the threshold, see the warning and the shell
comfortable for a form and for settings filled in thoughtfully comfortable for a long list — half as many rows fit on a screen as a queue row needs
The attribute on a container — a panel, a section, a dialog The attribute on every component — density is not a variant. The size of a control is chosen by --sm/--lg on the button
The default — writing nothing A density of your own as a number in an application — a new value gets a role, and the list of roles is in tokens
Changing the density of a whole region Mixing densities in one table — the columns will part, see the table

API

Attributes
NameValueWhat it does
attribute
data-density—compact comfortable. The absence of the attribute is the third, base value
Tokens
NameValueWhere from
token
--control-h-xs/sm/md/lg—one across every cell
--control-pad-sm/md/lg—one across every cell
--pad-panelvar(--space-5)base +14: density · scale
--pad-cardvar(--space-6)base +14: density · scale
--pad-cell-xvar(--space-4)base +14: density · scale
--row-pad-yvar(--space-3)base +14: density · scale
--gap-rowvar(--space-3)base +14: density · scale
--gap-inlinevar(--space-4)base +14: density · scale
--size-check15pxbase +14: density · scale
--size-switch-w30pxbase +14: density · scale
--size-switch-h18pxbase +14: density · scale
--size-thumb14pxbase +14: density · scale
--size-spinner14pxbase +14: density · scale
--size-gutter14pxbase +14: density · scale
--size-indent14pxbase +14: density · scale
--label-col104pxbase +4: scale

Why the kit works this way — the constitution · Open source under MIT, github.com/keshon/instrument