| |

Tailwind CSS 10 🎨 Dynamic Utility Values and Arbitrary Values Syntax (-[…])

Tailwind’s utility classes cover the common cases: p-4, text-lg, bg-blue-500, w-1/2. But real designs occasionally need a value that no utility provides. A layout might require top: 117px to align with an image, a brand color might exist only as a hex code from a client’s style guide, or a grid might need grid-template-columns: 1fr auto 2fr. Arbitrary value syntax — the square bracket notation — exists for these cases. It lets any CSS value be used with a Tailwind utility’s prefix, generating the correct property and value.

In v4, the arbitrary value syntax was extended with two major improvements. First, dynamic values mean many utilities accept bare numbers without brackets: p-17 and grid-cols-15 now work without configuration. Second, parenthesis shorthand text-(--my-var) expands to var() automatically, and CSS variable shorthand bg-(--brand) is cleaner than the bracket form. These additions reduce the need for brackets in the common cases while keeping them available for the genuinely arbitrary ones.

The risk is overuse. Arbitrary values bypass the design system: they introduce values that do not exist on the scale, they do not respond to theme changes, and they are invisible to the design tokens. The recommendation is to prefer theme tokens and dynamic values, and reserve brackets for one-off cases where no token exists.

Key point: Dynamic values let utilities accept any number without brackets: p-17, w-23, grid-cols-15. Arbitrary values use brackets for any CSS value: w-[117px], bg-[#bada55], grid-cols-[1fr_auto_2fr]. In v4, bg-(--brand) is shorthand for bg-[var(--brand)]. Prefer tokens and dynamic values; use brackets when nothing else fits.


Why arbitrary values exist

The gap between the scale and the design. Tailwind’s scale covers common spacing values (4, 8, 12, 16, 24, 32…) but a design comp may call for 13px of padding to align with a specific element. Creating a theme token for one use pollutes the design system. Arbitrary values let that one-off value exist without becoming part of the system.

The token coverage problem. A theme defines a color palette, but a third-party widget may require a specific hex code for a chart series. That color does not belong in the palette, but it is needed in one place. Arbitrary values provide access to it.

The CSS feature coverage problem. Tailwind does not have a utility for every CSS property. grid-template-columns, clip-path, background-image with a gradient, transform with a specific matrix — these are occasionally needed. Arbitrary values let any CSS property-value pair be expressed with a Tailwind prefix.

The dynamic CSS variable problem. A component may receive a runtime value from JavaScript, such as an accent color from a user preference. That value is not known at build time and cannot be a theme token. CSS variables are the mechanism, and Tailwind’s parenthesis syntax lets them be used directly in utilities.

The literal-string problem. Some CSS values contain spaces or special characters that conflict with class name syntax. grid-template-columns: 1fr auto 2fr contains spaces. Arbitrary values use underscores to represent spaces: grid-cols-[1fr_auto_2fr]. The parser converts underscores back to spaces when generating CSS.


a. Dynamic values: no brackets for numbers

Tailwind v4 made many utilities accept arbitrary numeric values without brackets. Where v3 required p-[17px], v4 accepts p-17, and the spacing scale multiplies it by --spacing:

<div class="p-17">17 × 0.25rem = 4.25rem padding</div>
<div class="w-23">23 × 0.25rem = 5.75rem width</div>
<div class="mt-42">42 × 0.25rem = 10.5rem margin-top</div>

This applies to spacing-derived utilities: p-*, m-*, gap-*, w-*, h-*, size-*, top-*, right-*, bottom-*, left-*, inset-*, and others. Any integer works; there is no validation that the value exists on a predefined scale.

Grid columns and rows also accept dynamic values:

<div class="grid grid-cols-15">15 columns</div>
<div class="grid grid-rows-8">8 rows</div>

The dynamic behavior changes the mental model. In v3, a class like p-17 would silently fail because 17 was not on the scale. In v4, it works, and the developer is expected to use judgment rather than relying on the framework to constrain them.


b. Arbitrary values: brackets for CSS values

When a value is not a bare number — a specific pixel value, a color, a percentage, a complex expression — brackets are required:

<!-- Fixed pixel values -->
<div class="w-[117px] h-[42px]">Fixed dimensions</div>

<!-- Color values -->
<div class="bg-[#bada55] text-[oklch(0.7_0.15_250)]">Custom colors</div>

<!-- Percentages and viewport -->
<div class="w-[50%] h-[calc(100dvh-4rem)]">Computed dimensions</div>

<!-- Complex CSS -->
<div class="grid grid-cols-[1fr_auto_2fr] gap-[3.5px]">
  Complex grid
</div>

<!-- Background images -->
<div class="bg-[url('/hero.jpg')]">Background image</div>

The syntax is the utility prefix, an opening bracket, the raw CSS value, and a closing bracket. Tailwind parses the value and generates the corresponding CSS declaration.

Underscores represent spaces in the value:

<div class="grid-cols-[repeat(3,minmax(0,1fr))]">...</div>
<div class="shadow-[0_4px_6px_-1px_rgba(0,0,0,0.1)]">...</div>

If an underscore is genuinely needed in the value (rare, mostly in URLs or content strings), escape it with a backslash: \_.


c. CSS variable shorthand in v4

Tailwind v4 introduced a parenthesis syntax for referencing CSS variables:

<div class="bg-(--brand-color)">Uses var(--brand-color)</div>

This is equivalent to bg-[var(--brand-color)] but cleaner. The parenthesis form implies var(), so the variable name is written without the function.

The syntax works for any utility:

<div class="text-(--heading-color)">Text color from variable</div>
<div class="w-(--sidebar-width)">Width from variable</div>
<div class="p-(--content-padding)">Padding from variable</div>

For variables that map to an ambiguous namespace, a type hint disambiguates:

<div class="text-(length:--font-size)">Font size from variable</div>
<div class="text-(color:--text-color)">Text color from variable</div>

The length: and color: prefixes tell Tailwind which CSS property to generate. This is needed when the utility prefix maps to multiple properties — text- can mean font-size or color — and the value is opaque because it is a variable rather than a literal.

For longer variable names, the bracket form is still valid, and the old shorthand bg-[--brand] is deprecated in favor of bg-(--brand).


d. Type hints for ambiguous namespaces

Many Tailwind utilities share a prefix but apply to different CSS properties. text-* can set font-size (text-lg) or color (text-red-500). With static values, Tailwind distinguishes by the value: text-lg has a size, text-red-500 has a color. With a CSS variable, the value is opaque, so the intent must be declared.

The type hint syntax uses parentheses inside the value:

<div class="text-(length:--size)">font-size: var(--size)</div>
<div class="text-(color:--color)">color: var(--color)</div>

The same pattern applies to other ambiguous prefixes. bg- is always background, so no hint is needed. border- can be width or color; border-(length:--width) and border-(color:--color) disambiguate. ring- follows the same pattern.

The hints are only required when the value is a CSS variable. A literal value is self-describing, and Tailwind can infer the property from the value’s form.


e. Using arbitrary values with modifiers and variants

Arbitrary values work with responsive prefixes, state variants, and other modifiers:

<div class="w-[117px] md:w-[240px]">Responsive arbitrary widths</div>
<div class="bg-[#bada55] hover:bg-[#c0ffee]">Custom colors with hover</div>
<div class="text-[14px] focus:text-[16px]">Arbitrary values with focus</div>

They also work with the important modifier and negative values:

<div class="!p-[13px]">Important arbitrary padding</div>
<div class="-mt-[7px]">Negative arbitrary margin</div>

The ! prefix marks the declaration as important. The - prefix negates the value, which works for margins and inset values.

Arbitrary values can be combined with opacity modifiers when the value is a color:

<div class="bg-[#bada55]/50">50% alpha on arbitrary color</div>

The opacity modifier is applied as a CSS color function with alpha, preserving the arbitrary color.


f. Arbitrary properties

When a CSS property has no corresponding Tailwind utility, the bracket syntax can be used directly as a property name:

<div class="[mask-type:luminance]">Mask property</div>
<div class="[clip-path:polygon(0_0,100%_0,100%_100%)]">Clip path</div>
<div class="[font-feature-settings:'liga'_0]">Font features</div>
<div class="[--my-var:42px]">Custom property definition</div>

The form is [property:value]. Tailwind generates exactly the declaration written. This is the escape hatch for anything Tailwind does not have a utility for, and it should be used sparingly because it bypasses the utility system entirely — no variants, no @theme integration, no dynamic behavior.

A particularly useful case is defining a CSS variable inline:

<div class="[--accent:#f97316]">
  <button class="bg-(--accent)">Uses the inline variable</button>
</div>

The variable is scoped to the element and its descendants, and the child utility reads it with the parenthesis syntax. This is a common pattern for passing values from a parent to children without JavaScript.


g. When to prefer tokens and dynamic values

Arbitrary values are powerful but easy to overuse. The decision framework:

Use a theme token when the value is part of the design system. A brand color, a standard spacing step, a typographic scale — these belong in @theme, generate utilities, and are available for theming.

Use a dynamic value when the value is a number. p-17 is cleaner than p-[68px] and respects the spacing scale even when the number is unusual.

Use a CSS variable when the value is runtime-dependent. A user-selected accent color, a computed layout dimension, a value from a third-party library — these come from var().

Use an arbitrary value when nothing else fits. A one-off pixel alignment, a complex grid-template-columns, a specific hex from a client’s brand guide, a property Tailwind does not cover.

Avoid arbitrary values when a token exists. p-[16px] when p-4 exists, or bg-[#3b82f6] when bg-blue-500 exists, fragments the design system. The point of tokens is that they can be changed centrally; hardcoded values cannot.


Complete Example Session

<!-- ============================================
PART 1: DYNAMIC VALUE WITHOUT BRACKETS
============================================ -->
<div class="p-17 mt-23 w-42">Dynamic spacing values</div>
<!-- ============================================
PART 2: FIXED PIXEL ARBITRARY VALUE
============================================ -->
<div class="w-[117px] h-[42px]">Exact dimensions</div>
<!-- ============================================
PART 3: ARBITRARY COLOR
============================================ -->
<div class="bg-[#bada55] text-[oklch(0.7_0.15_250)]">
  Custom colors
</div>
<!-- ============================================
PART 4: COMPLEX CSS VALUE
============================================ -->
<div class="grid grid-cols-[1fr_auto_2fr] gap-[3.5px]">
  Complex grid
</div>
<!-- ============================================
PART 5: CALC EXPRESSION
============================================ -->
<div class="h-[calc(100dvh-4rem)] w-[calc(50%-1rem)]">
  Computed dimensions
</div>
<!-- ============================================
PART 6: CSS VARIABLE SHORTHAND
============================================ -->
<div class="bg-(--brand-color) text-(--heading-color)">
  Values from CSS variables
</div>
<!-- ============================================
PART 7: TYPE HINT FOR AMBIGUOUS NAMESPACE
============================================ -->
<p class="text-(length:--font-size) text-(color:--text-color)">
  Explicit property from variable
</p>
<!-- ============================================
PART 8: RESPONSIVE AND STATE VARIANTS
============================================ -->
<div class="w-[117px] md:w-[240px] hover:bg-[#c0ffee]">
  Responsive and interactive arbitrary values
</div>
<!-- ============================================
PART 9: ARBITRARY PROPERTY
============================================ -->
<div class="[mask-type:luminance] [clip-path:polygon(0_0,100%_0,100%_100%)]">
  Properties without utilities
</div>
<!-- ============================================
PART 10: INLINE CSS VARIABLE AND CHILD USAGE
============================================ -->
<div class="[--accent:#f97316]">
  <button class="bg-(--accent) text-white px-4 py-2 rounded">
    Button using inline variable
  </button>
</div>

These ten parts cover dynamic values, fixed arbitrary values, arbitrary colors, complex grid values, calc expressions, CSS variable shorthand, type hints, responsive variants, arbitrary properties, and inline variable definition with child consumption. Each pattern uses the v4 syntax idiomatically.


Quick Reference

Value Syntax Forms

FormExampleOutput
Dynamic numberp-17padding: 4.25rem
Arbitrary valuep-[13px]padding: 13px
Arbitrary colorbg-[#bada55]background-color: #bada55
CSS variablebg-(--brand)background-color: var(--brand)
Type hinttext-(length:--x)font-size: var(--x)
Arbitrary property[mask-type:luminance]mask-type: luminance
Inline variable[--accent:#f97316]--accent: #f97316

Dynamic Values (No Brackets)

UtilityExampleNotes
p-*p-17Multiplied by --spacing
m-*m-23Multiplied by --spacing
w-*, h-*w-42Multiplied by --spacing
gap-*gap-13Multiplied by --spacing
grid-cols-*grid-cols-15Literal column count

Underscore to Space Conversion

WrittenRendered
grid-cols-[1fr_auto_2fr]grid-template-columns: 1fr auto 2fr
bg-[url('/img.jpg')]background-image: url('/img.jpg')
shadow-[0_4px_6px_rgba(0,0,0,0.1)]box-shadow: 0 4px 6px rgba(0,0,0,0.1)

When to Use What

ScenarioChoice
Value is a design tokenUse token utility (p-4)
Value is a bare numberUse dynamic (p-17)
Value is runtime-dependentUse CSS variable (p-(--x))
Value is one-off and fixedUse arbitrary (p-[13px])
Property has no utilityUse arbitrary property ([mask-type:...])

Best Practices

✅ Do This:

<div class="p-17">Dynamic value without brackets</div>
<div class="w-[117px]">One-off fixed dimension</div>
<div class="bg-(--brand)">Runtime variable reference</div>
<div class="text-(length:--font-size)">Type-hinted variable</div>
<div class="[--accent:#f97316]"><button class="bg-(--accent)">Button</button></div>

❌ Don’t Do This:

<div class="p-[16px]">When p-4 exists</div>
<div class="bg-[#3b82f6]">When bg-blue-500 exists</div>
<div class="p-[13px]">When p-3.5 is close enough</div>
<div class="w-[117px] md:w-[117px] lg:w-[117px]">No responsive variation</div>

Common Pitfalls

PitfallWhy It HappensFix
Class not generatedValue contains unescaped spacesUse underscores for spaces
Type hint missingCSS variable in ambiguous namespaceAdd (length:) or (color:)
Arbitrary value ignoredBrackets nested in variant syntaxCheck bracket placement
Overuse of bracketsNot knowing dynamic values workUse p-17 instead of p-[68px]
Token bypassedHardcoding a value that existsUse the token; reserve brackets for gaps
Escape underscore neededURL or content contains underscorePrefix with backslash \_

Real-World Examples

1. Specific Pixel Alignment

<div class="top-[117px]">Aligns with a specific image</div>

2. Client Brand Hex

<div class="bg-[#ff6b35]">Client brand color</div>

3. Complex Grid Template

<div class="grid grid-cols-[200px_1fr_auto]">
  Sidebar, content, action
</div>

4. Calc Height

<div class="h-[calc(100dvh-4rem)]">
  Full height minus header
</div>

5. Runtime Theme Variable

<div class="bg-(--user-accent)">User-selected accent</div>

6. Type Hint for Font Size

<p class="text-(length:--body-size)">Body text</p>

7. Inline Variable for Children

<div class="[--gap:1.5rem] flex gap-(--gap)">
  <div>Item</div>
  <div>Item</div>
</div>

8. Arbitrary Property

<div class="[writing-mode:vertical-rl]">Vertical text</div>

9. Responsive Arbitrary

<div class="w-[calc(100%-2rem)] md:w-[calc(50%-1rem)]">Responsive calc</div>

10. Dynamic Grid Columns

<div class="grid grid-cols-15 gap-4">15 column grid</div>

Visual

Value Syntax Forms

┌──────────────────────────────────────────────────────────────┐
│  FROM SIMPLE TO ARBITRARY                                    │
│                                                              │
│  p-4             Scale token (in the theme)                  │
│  p-17            Dynamic number (no bracket needed in v4)    │
│  p-[13px]        Arbitrary fixed value                       │
│  p-(--gutter)    CSS variable reference                      │
│  p-(length:--g)  CSS variable with type hint                 │
│  [padding:13px]  Arbitrary property (no utility)             │
│                                                              │
│  Prefer the first two. Use the rest when the value is        │
│  genuinely outside the scale or comes from runtime.          │
└──────────────────────────────────────────────────────────────┘

Underscores to Spaces

┌──────────────────────────────────────────────────────────────┐
│  grid-cols-[1fr_auto_2fr]                                    │
│       │                                                      │
│       ▼                                                      │
│  grid-template-columns: 1fr auto 2fr                         │
│                                                              │
│  Underscores in the class name become spaces in the CSS.     │
│                                                              │
│  bg-[url('/hero_image.jpg')]                                 │
│       │                                                      │
│       ▼                                                      │
│  background-image: url('/hero image.jpg')                    │
│                                                              │
│  A backslash-escaped underscore \_ preserves the underscore. │
└──────────────────────────────────────────────────────────────┘

CSS Variable Shorthand

┌──────────────────────────────────────────────────────────────┐
│  THREE WAYS TO REFERENCE A VARIABLE                          │
│                                                              │
│  Old bracket (deprecated):                                   │
│  bg-[--brand]                                                │
│                                                              │
│  Explicit var():                                             │
│  bg-[var(--brand)]                                           │
│                                                              │
│  Parenthesis shorthand (v4, preferred):                      │
│  bg-(--brand)                                                │
│                                                              │
│  All three produce: background-color: var(--brand)           │
└──────────────────────────────────────────────────────────────┘

Type Hints for Ambiguity

┌──────────────────────────────────────────────────────────────┐
│  WHEN THE PREFIX MATCHES MULTIPLE PROPERTIES                 │
│                                                              │
│  text-lg         → font-size (value is a size)              │
│  text-red-500    → color (value is a color)                 │
│  text-(--x)      → ambiguous; Tailwind cannot infer          │
│                                                              │
│  Type hint resolves it:                                      │
│  text-(length:--x)  → font-size: var(--x)                    │
│  text-(color:--x)   → color: var(--x)                        │
│                                                              │
│  Same pattern for border- and ring-:                         │
│  border-(length:--w) → border-width: var(--w)                │
│  border-(color:--c)  → border-color: var(--c)                │
└──────────────────────────────────────────────────────────────┘

Summary

ItemValue
Dynamic valuep-17, w-23, grid-cols-15 (no brackets)
Arbitrary valuew-[117px], bg-[#bada55]
CSS variable shorthandbg-(--brand) = bg-[var(--brand)]
Type hinttext-(length:--x), text-(color:--x)
Arbitrary property[mask-type:luminance]
Inline variable[--accent:#f97316]
UnderscoreRepresents a space in the value
Escape\_ preserves an underscore
Important modifier!p-[13px]
Negative-mt-[7px]
Opacitybg-[#bada55]/50

Key takeaways:

  • Dynamic values remove the need for brackets in numeric cases. In v4, p-17 and grid-cols-15 work without configuration because the spacing scale is a formula, not a lookup table.
  • Arbitrary values use brackets for anything that is not a bare number. Pixel values, hex colors, calc expressions, complex grid templates, and background images all use the [...] syntax.
  • Underscores represent spaces in arbitrary values. grid-cols-[1fr_auto_2fr] compiles to grid-template-columns: 1fr auto 2fr. Escape with \_ to preserve an underscore.
  • CSS variables use the parenthesis shorthand. bg-(--brand) is cleaner than bg-[var(--brand)] and is the v4 idiom.
  • Type hints resolve ambiguity. When a prefix maps to multiple properties and the value is a variable, (length:) and (color:) declare which property to generate.
  • Arbitrary properties cover any CSS. [property:value] generates exactly the declaration written, for properties Tailwind has no utility for.
  • Prefer tokens and dynamic values. Arbitrary values fragment the design system. Use them when nothing else fits, not as a first resort.
  • Arbitrary values work with variants. Responsive prefixes, state modifiers, the important flag, and negative values all compose with brackets.

Remember: Arbitrary values are the escape hatch that makes Tailwind complete. The utility system covers common cases; dynamic values cover arbitrary numbers; CSS variable syntax covers runtime values; brackets cover everything else. In v4, the dynamic and parenthesis syntaxes reduce the need for brackets, but brackets remain necessary for fixed pixel values, complex CSS, colors outside the theme, and properties without utilities. The discipline is in choosing the right tool: a theme token for values that belong to the design system, a dynamic number for values that fit the scale, a CSS variable for values that change at runtime, and brackets only for the genuine one-offs that no other mechanism covers. Used this way, arbitrary values extend the system without undermining it.



Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!