Utilities
ARC UI components own everything inside their shadow boundary and nothing outside it.
The space between components is yours, and in practice everyone writes the same
flex, gap and padding CSS to fill it — against 213 custom properties
base.css already publishes with no ergonomic way to use them.
272 generated, arc--prefixed classes, about
2.6 KB gzipped, covering spacing, layout and surface. It is a deliberate middle:
enough to lay out a page around ARC components, not enough to be a framework. This site
loads the stylesheet, so every demo on this page is the classes themselves, live.
Why not just use Tailwind
You can, and for most utility work you should. What Tailwind cannot do is know what
arc-card uses for its own padding.
These classes are generated from the same tokens.js the components compile
against, so .arc-p-md and a card's internal padding resolve to the same
value — and overriding one base token moves both:
Every declaration reads a var() rather than a literal, which is what keeps
that link intact. Use these where you want your layout to track the component system,
and anything else for the rest.
Install
Opt-in and standalone — nobody who only wants tokens pays for it. Every class is
arc- prefixed, because consumers run Tailwind or Bootstrap and an
unprefixed .flex would collide catastrophically. It costs the terseness that
makes utilities pleasant, and there is no way around it for a library.
Spacing
Every step of the --space-* scale, on padding, margin and gap. Suffixes are
logical, not physical: x/y for the inline and block axes,
s/e for start and end, t/b for block
start and end. A layout built from these mirrors under dir="rtl" without a
second stylesheet — the same class, both directions:
.arc-ps-xl.arc-ps-xl dir="rtl".arc-p-md | padding: var(--space-md) |
.arc-px-lg | padding-inline: var(--space-lg) |
.arc-py-sm | padding-block: var(--space-sm) |
.arc-ps-xl | padding-inline-start: var(--space-xl) |
.arc-m-0 | margin: 0 |
.arc-mx-auto | margin-inline: auto |
.arc-gap-md | gap: var(--space-md) |
.arc-gap-y-lg | row-gap: var(--space-lg) |
Steps are xs sm md lg xl 2xl 3xl 4xl, plus 0 everywhere and
auto on margins.
Layout
.arc-flex .arc-items-center .arc-justify-between .arc-col-span-2.arc-grid-cols-3.arc-gap-sm.arc-col-span-full- Display —
.arc-flex,.arc-inline-flex,.arc-grid,.arc-block,.arc-contents,.arc-hidden. - Flex —
.arc-flex-col,.arc-flex-wrap,.arc-flex-1,.arc-grow,.arc-shrink-0. - Alignment —
.arc-items-center,.arc-justify-between,.arc-self-end. - Grid —
.arc-grid-cols-1through-6,.arc-col-span-*,.arc-col-span-full. - Size —
.arc-w-full,.arc-h-full,.arc-max-w-full, and.arc-min-w-0, which is the fix for a flex child that refuses to shrink and text that refuses to ellipsis.
Surface
.arc-bg-card .arc-border .arc-rounded-md .arc-shadow-lg.arc-text-secondary .arc-text-sm.arc-text-accent-primary .arc-font-mono.arc-text-primary | color: var(--text-primary) |
.arc-text-lg | font-size: var(--text-lg) |
.arc-bg-card | background-color: var(--bg-card) |
.arc-border | border: 1px solid var(--border-default) |
.arc-border-subtle | border-color: var(--border-subtle) |
.arc-rounded-md | border-radius: var(--radius-md) |
.arc-shadow-lg | box-shadow: var(--shadow-lg) |
.arc-font-mono | font-family: var(--font-mono) |
Colors use the token names directly, so .arc-text-primary is the foreground
color and .arc-text-lg is a type size — the same split
--text-primary and --text-lg already have. The generator fails
the build if a future token ever makes those two collide.
Font classes name the five roles, not typefaces: .arc-font-body.arc-font-label.arc-font-mono.arc-font-display.arc-font-quote
Limits
- Light DOM only. A class cannot cross a shadow boundary — these style
the space around ARC components, never anything inside one. Use
::part()and the CSS custom properties for that. - No responsive or state variants. No
sm:, nohover:. That is where a utility layer becomes a framework, and this one is deliberately not that. Write a media query. - No arbitrary values. The scale is the point — a class that resolves to an arbitrary pixel value is not tracking the token system.
- Requires the tokens. Every class reads a
var()— loadbase.css, or define the same variables yourself.