Spacing
Responsive, semantic spacing tokens for layout, section, and component rhythm.
CreateUI ships a set of semantic spacing tokens. You write one class, such as gap-layout-xl, and it resolves to a different value at every breakpoint (48px on mobile, 64px on tablet, 128px on desktop). The responsive curve lives inside the token, so you stop hand-tuning spacing per screen size and the whole product keeps a consistent rhythm.
The problem it solves
Responsive spacing usually means stacking breakpoint variants on every element. It is verbose, easy to get wrong, and impossible to change globally.
With tokens, the same intent is two classes:
The win is not just shorter class lists:
- One source of truth. The mobile, tablet, and desktop values are defined once per token. Every surface that uses
gap-layout-xlscales identically. - Global changes are one edit. Want page rhythm to feel tighter on tablet? You change the token, not hundreds of
md:variants spread across the codebase. - No drift. Designers and engineers reference the same named scale, so spacing stays on-system instead of becoming a pile of one-off
gap-7values.
The three scales
Spacing is split into three scales by what sits on either side of the gap. Pick the scale that matches the size of the things you are spacing.
Rule of thumb: the bigger the things on either side of the gap, the higher the scale. A gap between two full sections is layout. A gap between two lines of text inside a card is component.
How a token responds
Every token carries three values, one per breakpoint range:
- Mobile: 320 to 767px
- Tablet: 768 to 1279px
- Desktop: 1280px and up
A single utility class emits all three. For example, gap-layout-xl produces:
You never write the breakpoints yourself. The token already knows its full curve.
Token reference
Values below are the resolved pixels at each breakpoint, on the default --spacing base of 4px. Each bar is drawn at its live token width, so it resizes with the viewport exactly as the token does.
Layout
Page-level spacing.
Section
Section-level spacing.
Component
Component-internal spacing.
component-sm and component-xs are flat on purpose. Tight internal spacing reads the same at every screen size, so these tokens hold one value across all breakpoints.
Using the tokens
The token name plugs into any Tailwind spacing utility. Tailwind v4 generates the full set automatically, so all of these work:
The same applies to m-, mx-, my-, mt-, gap-x-, gap-y-, and the rest of the spacing utilities.
Prefer px-component-none over px-0 when you intentionally remove horizontal padding from a token-driven element. It keeps the intent explicit: this is a deliberate override of a semantic token, not an arbitrary zero.
Choosing semantic vs raw spacing
Semantic tokens scale across breakpoints. That is exactly what you want when the design opts into responsive spacing, and exactly what you do not want for a fixed, static gap.
Use the token only when the design references one
Reach for a semantic class only when the design references a semantic spacing token (for example a Figma variable like component/sm). When the design specifies a static value (for example space-4), use the standard Tailwind class such as gap-4. Applying a semantic token to something meant to be static silently opts it into breakpoint scaling.
Real-world example
The three scales compose naturally: layout frames the section, section spaces the groups inside it, and component handles the internals of each card.
Resize the viewport and every gap retunes itself. You did not write a single breakpoint variant.
How it works
You do not need this to use the tokens, but it helps to know the numbers are generated, not hand-written.
The pipeline runs from a single data file to Tailwind utilities:
-
apps/v4/lib/createui-spacing.tsdefinesTOKENS. Responsive values use ther(mobile, tablet, desktop)helper; a single number means a flat value.apps/v4/lib/createui-spacing.ts -
apps/v4/registry/config.tsconsumes the tokens viabuildSpacingCssVars(), turning each into a responsive value string. -
The CLI (
packages/createui/src/utils/updaters/update-css-vars.ts) splits each token across breakpoints, writing the desktop value to:rootand the smaller values into max-width media queries.generated in app globals.css -
An
@theme inlineblock registers each--spacing-*variable, and Tailwind v4 auto-generates thegap-*,p-*,m-*utilities from it.
Programmatic access
For Storybook, tests, or runtime logic, createui-spacing.ts exports helpers to resolve tokens in JavaScript.
BreakpointName is "mobile" | "tablet" | "desktop".
Changing or adding a token
Edit the token data
Update TOKENS in apps/v4/lib/createui-spacing.ts. Use r(mobile, tablet, desktop) for a responsive value, or a single number for a flat one.
Rebuild the registry
Run the registry build so the generated CSS variables pick up the change.
Regenerate in consumer projects
In a project that uses CreateUI, createui init regenerates the CSS variables and media queries from the updated tokens.