Skip to content

enforce-consistent-variable-syntax ​

oxlint rule that writes Tailwind CSS variable values one way — shorthand bg-(--primary) or bg-[var(--primary)] — and rewrites the other form.

At a glance ​

AutofixEditor suggestionsDesign systemOptions
YesYesNot usedsyntax

What this rule does ​

Tailwind v4 added a shorthand for arbitrary CSS variable values: bg-(--primary) is sugar for bg-[var(--primary)]. Both produce the same CSS. This rule picks one of the two syntaxes and rewrites every class that uses the other. Autofix on the first offender per location, editor suggestion on subsequent ones.

The rule only touches the simple something-[var(--name)] ↔ something-(--name) pair. Complex expressions like bg-[color-mix(in_srgb,var(--primary),transparent)] are left alone — they don't have a shorthand form. Important modifier (!flex / flex!) and variant chains (hover:, dark:) round-trip correctly.

DS-independent — works without settings.tailwindcss.entryPoint. Pure string transform on the utility shape; no design-system lookup.

Options ​

syntax ​

'shorthand' | 'explicit', default 'shorthand'.

'shorthand' rewrites bg-[var(--primary)] → bg-(--primary). This is the Tailwind v4 idiomatic form and the recommended choice for new projects. 'explicit' rewrites the other direction — bg-(--primary) → bg-[var(--primary)] — useful if you still target older tooling or if your team prefers the longer form for grepability.

jsonc
{ "tailwindcss/enforce-consistent-variable-syntax": ["error", { "syntax": "shorthand" }] }

Examples ​

✗ Incorrect ​

tsx
// Default shorthand — explicit form is reported
<div className="bg-[var(--primary)]" />
//              ~~~~~~~~~~~~~~~~~~~  → bg-(--primary)

// With a variant chain
<div className="dark:hover:text-[var(--color)]" />
//              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  → dark:hover:text-(--color)

// With important modifier
<div className="!bg-[var(--primary)]" />
//              ~~~~~~~~~~~~~~~~~~~~  → !bg-(--primary)

✓ Correct ​

tsx
// Shorthand (default)
<div className="bg-(--primary) text-(--text-color)" />

// Variants and important round-trip cleanly
<div className="hover:bg-(--primary) font-bold!" />

// Complex expressions are NOT rewritten
<div className="bg-[color-mix(in_srgb,var(--primary),transparent)]" />

Interactions with other rules ​

  • enforce-canonical: this rule is the single owner of variable syntax. Because bg-(--x) is Tailwind's canonical form, enforce-canonical would otherwise report the same bg-[var(--x)] → bg-(--x) swap; instead it cedes the plain bracket↔paren conversion to this rule (the same way it cedes v3 renames to no-deprecated-classes). That prevents a duplicate diagnostic and, when this rule is set to explicit, an autofix fight. enforce-canonical still handles variable canonicalizations that aren't a plain swap — a value that maps to a named token (rounded-[var(--radius-sm)] → rounded-sm) or an opacity-modifier form (text-[var(--color-text)]/90 → text-(--color-text)/90).
  • no-unnecessary-arbitrary-value: mostly disjoint — it converts an arbitrary value to its named equivalent (bg-[#ff0000] → bg-red-500). They overlap only when a variable's value matches a named utility: on bg-[var(--color-red-500)] that rule fires (→ bg-red-500) and this one fires too (→ bg-(--color-red-500)). The two propose different targets, so enable the one whose policy you want — or run no-unnecessary-arbitrary-value first if you prefer the named utility.
  • prefer-theme-tokens: when a CSS variable matches a @theme token, that rule swaps to the named utility (bg-(--primary) → bg-primary if --primary is declared in @theme). Run that one before this one if you want both transforms.

When to disable it ​

  • You target tooling older than Tailwind v4: the shorthand form isn't supported. Set syntax: 'explicit' instead of disabling, so you get the rewrite in the safe direction.
  • Mixed-syntax codebase mid-migration where consistency isn't yet the goal.

Released under the MIT License.