Foundations

Sizing & layout.

Fit the content. Reach the controls.

Independent size contracts keep controls predictable while containers, viewport thresholds, and gutters make layouts adapt.

Six contracts, one foundation

Spacing describes relationships. Sizing describes the box that holds or activates content. Density changes spacing only: it never rewrites control heights, icon sizes, interaction targets, viewport breakpoints, or gutters. The values below are Dixy’s initial web contracts, chosen to extend the existing control scale.

Sizing tokens at a 16px root
FamilyTokenReference sizeCSS value
control--dixy-size-control-sm32px2rem
control--dixy-size-control-md40px2.5rem
control--dixy-size-control-lg48px3rem
icon--dixy-size-icon-xs12px0.75rem
icon--dixy-size-icon-sm16px1rem
icon--dixy-size-icon-md20px1.25rem
icon--dixy-size-icon-lg24px1.5rem
icon--dixy-size-icon-xl32px2rem
icon--dixy-size-icon-2xl48px3rem
target--dixy-size-target-minimum24pxmax(24px, 1.5rem)
target--dixy-size-target-comfortable44pxmax(44px, 2.75rem)

Controls retain sm / md / lg heights of 32 / 40 / 48px. Icons use 12 / 16 / 20 / 24 / 32 / 48px; an icon’s size does not define its hit area. Button icons are 16px, or 20px on large buttons. IconButton’s actual box is at least 44 × 44px, even when its size prop is sm. Loading icons use the 16px token.

Try the complete layout

Measuring the layout…

A workspace that fits

Container gutters follow the viewport. Control size stays independent of density.

No action yet.

sizing-layout-example.tsx
import "@dixy-ui/react/styles.css";
import { Theme } from "@dixy-ui/react";
import { useState, type CSSProperties } from "react";
import {
  Button,
  Container,
  Field,
  Heading,
  IconButton,
  Inline,
  Stack,
  Text,
  TextField,
  Theme as DensityScope,
} from "@dixy-ui/react";

Interaction targets have their own floor

The minimum token uses a 24 CSS pixel floor; comfortable uses a 44 CSS pixel floor. Both grow with the root font size. These floors survive smaller root fonts, and remain independent of density. Buttons and inputs use the minimum policy by default; icon buttons always use the larger floor. On devices reporting any coarse pointer, buttons and inputs also use at least the comfortable target. The policy enlarges the actual box, so adjacent targets do not overlap through invisible pseudo-elements.

The WCAG 2.2 minimum target criterion uses 24 × 24 CSS pixels with exceptions; the enhanced criterion uses 44 × 44. Token adoption alone does not establish conformance: content, spacing, focus, labels, and real device use still need review. The playground’s comfortable policy can test larger boxes on a fine-pointer desktop.

target-policy.css
.touch-friendly-region {
  --dixy-interaction-target: var(--dixy-size-target-comfortable);
}
/* Apply to a Theme root to carry the override through Dialog portals. */

Containers and responsive gutters

Container maximums, including gutters
TokenReference maximumREM
--dixy-container-sm640px40rem
--dixy-container-md768px48rem
--dixy-container-lg1024px64rem
--dixy-container-xl1280px80rem

Container defaults to xl, centers with logical margins, and stays within its parent. Its maximum includes inline padding. Gutters use the existing immutable space scale: base → space.200 (16px), sm → space.300 (24px), lg → space.400(32px). They follow the viewport, including when a Container sits in a narrow parent. These are viewport queries, not container queries.

layout.css
@import "@dixy-ui/tokens/spacing.css";
@import "@dixy-ui/tokens/layout.css";

.page {
  box-sizing: border-box;
  inline-size: 100%;
  max-inline-size: var(--dixy-container-xl);
  margin-inline: auto;
  padding-inline: var(--dixy-layout-gutter);
}

Container API

Generated from Container’s local sizing contract. Native attributes, typed refs, className, style, and semantic element composition through as are forwarded, as they are for Stack and Inline.

PropTypeDefault
size"sm" | "md" | "lg" | "xl"

Maximum inline size, including the responsive gutters.

xl

Breakpoints are shared thresholds

Viewport min-width queries
NameReference pixelsGenerated media condition
sm640px(min-width: 40rem)
md768px(min-width: 48rem)
lg1024px(min-width: 64rem)
xl1280px(min-width: 80rem)
wide1536px(min-width: 96rem)

CSS custom properties expose threshold values for inspection, but cannot be used in media query conditions. The generator emits literal rem conditions from the canonical breakpoints; JavaScript uses minWidth with matchMedia. Media-query rem units follow the browser’s initial font size, while ordinary rem lengths follow the document root. Choose a threshold when content needs a new arrangement, not by device name. xl and wide remain available without increasing gutters beyond 32px.

tokens.ts
import { size, container, layoutGutter, minWidth } from "@dixy-ui/tokens";

const controlHeight = size("control", "md");
const iconSize = size("icon", "sm");
const contentMaximum = container("lg");
const padding = layoutGutter;
// Browser code only; the token module itself is safe for SSR.
const query = window.matchMedia(minWidth("lg"));

Adapt without clipping content

Keep inputs fluid, wrap actions, and use min-inline-size: 0 on flex/grid children. Avoid fixed-height content panels. Control tokens define nominal heights; the target policy can increase the rendered height. Keep icons decorative unless they communicate content, name icon-only actions, and preserve visible focus indicators. Test long labels, RTL, enlarged text, 320px reflow, and real 200%/400% browser zoom. Resizing a viewport is not the same as zooming. These foundations add no animation.

Existing --dixy-height-sm/md/lg overrides remain available as aliases to the new control sizing contract. Override those on Theme roots for legacy control-height customization; use --dixy-size-control-* for new work. No responsive prop engine, new router, or Tailwind dependency is introduced.