Theme
On this page (8)

§One scale, two vocabularies

A numeric size is a quantity, not an index: w-4 means four base units. Named properties select useful points on the same scale. The default --size-base reads the existing --spacing token, with 0.25rem as its fallback. These are predictable design defaults, not a claim of universally optimal dimensions.

PropertyBase unitsAt a 16px root
--size-base14px
--size-xs28px
--size-sm312px
--size-md416px
--size-lg624px
--size-xl832px

§Density is not display resolution

CSS pixels already abstract device pixels; rem follows the root font size. No device-pixel-ratio multiplier and no root-font reset are added. Layout density changes opted-in gaps, margins, padding and container gutters—not numeric widths, heights, icons or typography. CSS Values and Units

§The sizing toolbox

Real UI mixes fixed and flexible sizes on one row: a size-10 shrink-0 avatar square, a flex-1 min-w-0 text column that absorbs the remaining width without widening the page, and a shrink-0 action that keeps its own size. The same scale sizes icon boxes inside buttons - a size-4 SVG lines up with the label's line height.

§Guides

The scale has three faces, each with its own page:

§Size the target, not only the icon

WCAG 2.2 AA uses a 24 × 24 CSS-pixel target-size criterion, with exceptions including sufficient spacing. The enhanced AAA criterion uses 44 × 44 CSS pixels, also with exceptions. These concern the interactive target, not the visible icon. WCAG 2.2: Target Size (Minimum), AA · WCAG 2.2: Target Size (Enhanced), AAA

Use 44px minimum dimensions as a starting point for touch-oriented controls; assess the actual clickable shape and surrounding targets. A minimum-size declaration alone does not certify WCAG conformance. Existing buttons are not silently resized by this module.

<button class="btn" type="button" aria-label="Add project"
  style="min-inline-size:44px;min-block-size:44px;">
  <svg class="size-4" viewBox="0 0 16 16" aria-hidden="true">
    <path d="M8 2v12M2 8h12" fill="none" stroke="currentColor"/>
  </svg>
</button>

§Install only what you use

<link rel="stylesheet" href="../theme/utils/default-semantic-tokens.css">
<link rel="stylesheet" href="../theme/utils/sizing.css">
<link rel="stylesheet" href="../theme/utils/layout.css">
<link rel="stylesheet" href="../theme/utils/accessibility.css">
<!-- Load the component stylesheets you actually use next. -->
<link rel="stylesheet" href="../components/button/button.css">

The optional modules live beside the theme assets so the existing copy build and CDN mirror work unchanged. They are not part of the replaceable semantic-token export. Both files declare @layer components, utilities; load them before component CSS so that order is established first. A later layer declaration cannot reorder layers that already exist. Normal unlayered application CSS overrides both.

§Override properties, not generated classes

/* Global application CSS; do not edit a tweakcn export. */
:root {
  --size-base: 0.3rem;
  --layout-density: 1;
}
/* Local scale: redeclare aliases at this explicit boundary. */
.compact-panel {
  --size-base: 0.2rem;
}
<section class="compact-panel" data-size-scope>
  <div class="w-16 h-8">Local scale</div>
  <div style="padding:var(--size-sm);">Named local size</div>
</section>

Custom-property formulas resolve before inheritance. When a local --size-base changes, add data-size-scope on that element to recompute its named aliases. Numeric utilities use the base directly. Prefer custom properties or a small semantic rule to inventing unsupported class names.

§Platform references

CSS custom-property inheritance · CSS cascade layers

Comments, ideas or improvements? Edit this page's source on GitHub