design token

Spacing

Consistent scale for padding, margins, gaps, and layout across all components and frameworks.

A consistent scale for padding, margins, gaps, and other spatial relationships. Every step is a multiple of one unit, the --spacing-unit custom property: md is calc(var(--spacing-unit, 0.4rem) * 4). The unit defaults to 4px (SPACING_UNIT_PX), written in rem against the design system’s 10px root (html { font-size: 62.5% }), so md is 16px and the scale still follows the user’s browser font size.

Scale

scale · spacing
none
0 · 0px
5xs
0.1rem · 1px
4xs
0.2rem · 2px
3xs
0.4rem · 4px
2xs
0.6rem · 6px
xs
0.8rem · 8px
sm
1.2rem · 12px
md
1.6rem · 16px
lg
2rem · 20px
xl
2.4rem · 24px
2xl
2.8rem · 28px
3xl
3.2rem · 32px
4xl
3.6rem · 36px
5xl
4rem · 40px
6xl
4.4rem · 44px
7xl
4.8rem · 48px
8xl
5.2rem · 52px
9xl
5.6rem · 56px
10xl
6rem · 60px
11xl
6.4rem · 64px

The sub-unit steps (5xs–2xs) cover hairline gaps that dense UI needs: 5xs is a quarter of the unit (1px), 4xs half (2px), 3xs one unit (4px) and 2xs one and a half (6px). From md (4 units, 16px) upward the scale is linear, +1 unit per step. none is a literal 0, handy for resetting a gap inside a responsive object.

Density

data-density="compact" or "relaxed" on an element swaps the unit to 3px or 5px for everything inside it, and every step keeps its multiplier: md is 12px compact, 16px default, 20px relaxed. Control-row padding and gaps follow, because they are spacing tokens; control heights, type and the 24px raster line stay put. The Appearance block sets it on <html> and remembers the choice.

<html data-density="compact">
  …
</html>
<aside data-density="compact">…</aside>
<!-- or any subtree -->

default is the absence of the attribute.

Spacing and the 24px line

The raster counts vertical space in text lines, and one line is 24px (16px × 1.5) — exactly 6 spacing units. So the spacing scale nests inside the line, but only two tokens land on a whole number of lines: xl (24px, one line) and 7xl (48px, two lines). Every other token is a fraction of a line. When a gap must stay on the raster, pass a line count to the Grid (gutter={1}) instead of a token.

Control padding tokens

Control rows (Button, Input, Select, and friends) take their padding from semantic aliases generated from the sizing presets, so the sizing pattern never carries a literal table. They are thin references to the scale above:

tokens · spacing.control
tokenvaluedescription
control.padX.xs{spacing.xs}8px
control.padX.sm{spacing.sm}12px
control.padX.md{spacing.md}16px
control.padX.lg{spacing.xl}24px
control.padX.xl{spacing.3xl}32px
control.padY.xs{spacing.3xs}4px
control.padY.sm{spacing.2xs}6px
control.padY.md{spacing.xs}8px
control.padY.lg{spacing.sm}12px
control.padY.xl{spacing.md}16px
<div
  className={css({ paddingX: "control.padX.md", paddingY: "control.padY.md" })}
>
  Aligns with a medium control
</div>

Usage

Padding & Margin

import { css } from "@pindoba/styled-system/css";

<div className={css({ padding: "md" })}>Uniform padding</div>

<div className={css({ paddingX: "lg", paddingY: "sm" })}>
  Asymmetric padding
</div>

<div className={css({ marginX: "auto", marginY: "lg" })}>
  Centered with vertical margin
</div>

Gap

<div className={css({ display: "flex", gap: "md" })}>
  <div>Item 1</div>
  <div>Item 2</div>
</div>

<div className={css({
  display: "grid",
  gridTemplateColumns: "repeat(3, 1fr)",
  gap: "lg",
})}>
  <div>Grid item</div>
  <div>Grid item</div>
  <div>Grid item</div>
</div>

Responsive Spacing

<div
  className={css({
    padding: { base: "sm", md: "md", lg: "lg" },
  })}
>
  Responsive padding
</div>

Best Practices

  • 5xs–2xs: Hairlines, icon gaps, compact elements
  • xs: Tight spacing between related elements
  • sm: Close relationships, form field gaps
  • md: Standard spacing, comfortable default
  • lg–xl: Generous spacing, component separation
  • 2xl–11xl: Major layout spacing, hero sections
  • Spacing tokens are for padding, margin and gap. Sizes (width, height) use the sizes tokens