arbitrary values

[check: …]
📖 Pair this live Tailwind demo with the companion guide (.md) — this page is the rendered ground truth. ↗ Builds on frontend/tailwind: customization (the @theme system — arbitrary values are the escape hatch when no token fits).

built-in scale → arbitrary value: the escape hatch

Tailwind ships a curated scale: w-4 = 1rem, p-8 = 2rem, text-cyan-500 = a specific oklch. But design specs aren't always on the scale — a Figma frame is 17rem wide, a brand color is #1da1f2, a grid is 1fr 2fr 1fr. Arbitrary values let you write the exact CSS value inline — no new utility, no @theme entry, no plugin. The JIT compiler reads the brackets and emits one rule.

syntaxwhat it doesexamplecompiles to
[value] one-shot arbitrary value w-[17rem] width: 17rem
[type:value] type hint — disambiguates the compiler [color:#fff] · [length:300px] color: #fff · width: 300px
underscore → space JIT converts _ inside [] to a space grid-cols-[1fr_2fr_1fr] grid-template-columns: 1fr 2fr 1fr
escaped underscore \_ keeps a literal underscore bg-[length:18px\_18px] background-size: 18px 18px
CSS variable reference a token defined in @theme or :root bg-[var(--color-brand)] background-color: var(--color-brand)
URL background-image from a path bg-[url('/hero.jpg')] background-image: url('/hero.jpg')

1 · arbitrary width — w-[Nrem] computes to N × 16px

Drag the slider. The box below uses w-[17rem] — an arbitrary rem value. 1rem = 16px (browser default), so w-[17rem] must compute to 272px. The gold-check pins exactly this fact via getComputedStyle().

17rem = 272px
w-[17rem]

computed width: —

2 · arbitrary colors — hex, rgb(), and var() bridges

Brand colors rarely sit on Tailwind's palette. Arbitrary values accept any CSS color syntax — #hex, rgb(), hsl(), oklch(), or var(--token). The right card pulls its color from the @theme token --color-brand — the same token a bg-brand utility would use, proving arbitrary values and @theme are interoperable, not competing.

hex

bg-[#1da1f2]

Twitter blue, off the Tailwind scale.

rgb()

bg-[rgb(44,46,51)]

Full rgb() syntax, no alpha shorthand.

var() → @theme

bg-[var(--color-brand)]

Same token as bg-brand — interoperable.

Type hint: when the value is ambiguous (e.g. a CSS variable that could be a color or a length), prefix with [color:var(--x)] or [length:var(--x)] so the JIT picks the right CSS property.

3 · arbitrary grid — underscores become spaces

Multi-value CSS properties (grid-template-columns, transform, box-shadow) need spaces. Class names can't contain spaces, so inside [] the JIT treats _ as a space: grid-cols-[1fr_2fr_1fr]grid-template-columns: 1fr 2fr 1fr.

header · grid-cols-[1fr_2fr_1fr] + col-span-3
1fr
2fr (wider)
1fr
footer · grid-rows-[auto_1fr_auto]

Escaped underscore: to keep a real _ (e.g. in a filename or background-size), write \_: bg-[length:18px\_18px]background-size: 18px 18px (here the _ became a space, the \_ would stay literal).

4 · arbitrary URL — bg-[url('...')] background images

Background images inline: bg-[url('...')]. Pair with bg-cover, bg-center, and an overlay. The URL must be quoted (single quotes inside the brackets) so the JIT doesn't choke on spaces or query strings. Below uses an inline SVG data-URI so the demo is self-contained.

bg-[url('data:image/svg+xml…')]

Production note: for real images, prefer bg-[url('/hero.jpg')] with a path from your public/ dir. The JIT emits background-image: url('/hero.jpg') verbatim.

5 · live playground — type a value, watch it compile

Type any arbitrary value below. The class is applied live and the computed style is read back — proving the JIT compiled your bracket on the fly. Try #e74c3c, oklch(0.7 0.2 145), or var(--color-accent2).

live preview

computed background-color: —

intent → pattern

intentpatternwhy
off-scale length w-[17rem] · p-[13px] · gap-[0.75rem] exact value from a spec, no need to extend the theme for a one-off
brand color off the palette bg-[#1da1f2] · text-[rgb(44,46,51)] any CSS color syntax inline
ambiguous value → force property border-[color:var(--brand)] · w-[length:var(--w)] type hint tells JIT which property to emit
multi-value property grid-cols-[1fr_2fr_1fr] · shadow-[0_4px_12px_rgba(0,0,0,.5)] underscores inside [] become spaces
literal underscore in value bg-[length:18px\_18px] \_ keeps the underscore (background-size, filenames)
reuse a design token inline bg-[var(--color-brand)] · w-[var(--card-width)] bridge to @theme — token stays the single source of truth
background image bg-[url('/hero.jpg')] bg-cover bg-center emit background-image: url(...) without a custom utility
z-index, content, anything z-[9999] · content-['→'] · rotate-[17deg] any utility that takes a value accepts arbitrary brackets