---
title: "Tailwind v4: Arbitrary Values"
slug: "tailwind-arbitrary-values"
category: "frontend"
tags: ["tailwind", "css", "frontend", "arbitrary-values", "design-tokens", "escape-hatch"]
status: "stable"
last_updated: 2026-05-14
summary: "Use [..] bracket syntax as a temporary escape hatch; extract to @theme after the third use; avoid a codebase full of hard-coded values."
related: ["[[frontend/tailwind]]", "[[frontend/css]]", "[[frontend/tailwind-theme]]", "[[frontend/tailwind-variants]]", "[[comparisons/tailwind-vs-css-modules]]"]
---

## Overview

Arbitrary values let you write any CSS value inline as a Tailwind class: `w-[412px]`, `bg-[oklch(0.72_0.18_264)]`, `mt-[calc(var(--header-height)+1rem)]`. They exist to handle values the design system has not yet tokenized, not to replace the design system. The parent reference is [[frontend/tailwind]]; for the token system see [[frontend/tailwind-theme]].

## Extract to `@theme` after the third use

One arbitrary value in a file is a one-off. Two uses in the same component might be a coincidence. Three uses of the same value across the codebase is a missing design token.

```css
/* Before: the same value scattered across three files */
/* w-[412px] in card.tsx, modal.tsx, sidebar.tsx */

/* After: one token, three uses */
@theme {
  --width-panel: 412px;
}
/* Now use: w-panel */
```

This is the extraction rule. It has no exception for "convenient" or "obvious" values. The point of the design system is that every value has a name and a home.

## Use arbitrary values for genuinely one-off overrides

Some values are legitimately one-off: a clip-path, a background gradient with specific stops, a CSS grid template that is unique to one layout. For these, arbitrary values are the right tool.

```html
<div class="[clip-path:polygon(0_0,100%_0,100%_80%,0_100%)]">
<div class="bg-[linear-gradient(135deg,oklch(0.72_0.18_264),oklch(0.55_0.22_310))]">
<div class="grid-[auto_1fr_auto]">
```

If the value appears once and there is no design-system motivation to name it, an arbitrary value is correct. Document why with a comment if the value is not self-explanatory.

## Use arbitrary properties for non-standard CSS

Any CSS property can be set with the `[property:value]` syntax.

```html
<div class="[content-visibility:auto] [contain-intrinsic-size:0_500px]">
<p class="[text-wrap:pretty] [hyphenate-limit-chars:8_4_4]">
```

This works for experimental properties, vendor-specific properties, and CSS properties Tailwind does not expose as named utilities. No plugin or custom utility needed for a single-use case.

## Write arbitrary variants for one-off selectors

Arbitrary syntax also applies to variants. Use `[&...]` for selectors that do not have a named variant.

```html
<ul class="[&>li]:py-2 [&>li:first-child]:pt-0 [&>li:last-child]:pb-0">
```

The `&` refers to the element bearing the class. This handles `nth-child`, `not`, `is`, attribute selectors, and anything else CSS supports. If the pattern appears in three or more places, define a `@custom-variant` instead; see [[frontend/tailwind-variants]].

## Avoid using arbitrary values to work around a missing token

Arbitrary values that should be tokens are the most common form of design system debt.

Signs you are using an arbitrary value when you should add a token:

- The value matches a number from the design spec but not from the default Tailwind scale.
- You have copied the same arbitrary value from another component by muscle memory.
- A search for the value in your codebase returns more than two results.

When you find one of these, add the token to `@theme`, search-and-replace the arbitrary values, and commit the cleanup as a separate commit from the feature work.

## Prefer `var(--token)` over arbitrary values in complex expressions

Complex `calc()` or `clamp()` expressions that reference design tokens read better using `var()` than repeating raw values.

```html
<!-- Less clear: magic numbers, no design intent expressed -->
<div class="mt-[calc(64px+1rem)]">

<!-- Better: names express intent, calc stays readable -->
<div class="mt-[calc(var(--spacing-header)+var(--space-4))]">
```

Arbitrary values containing `var()` references are still arbitrary values, but they preserve the connection to the design system.

## Keep arbitrary values out of shared components

Shared components should use named tokens. An arbitrary value in a component that is copied across many projects becomes a maintenance problem when the design system changes.

If you are building a component for a library or design system, every value should come from a `@theme` token or a CSS custom property that the consumer can override. Arbitrary values are for product code, not for reusable components.

## Related

- [[frontend/tailwind]]
- [[frontend/css]]
- [[frontend/tailwind-theme]]
- [[frontend/tailwind-variants]]
- [[frontend/tailwind-plugins]]
- [[comparisons/tailwind-vs-css-modules]]
