Overview
Tailwind v4 lets you extend and override utilities directly inglobal.css using the @utility and @theme directives โ no config file required. This guide covers three common scenarios:
- Variable-driven utilities โ create a utility whose value is injected at runtime via a CSS variable
- Brand-new utilities โ add a class that has no Tailwind equivalent
- Overriding existing utilities โ change what a built-in Tailwind class does
Variable-Driven Utilities
Sometimes you need a utility class whose value isnโt known until runtime. A common example is padding that accounts for a navigation header height, which is only available after the layout renders.Example: p-safe-header
Step 1 โ Declare the variable in global.css
Use @theme static so the variable is always available in JavaScript even before it is updated, and define the utility with @utility:
global.css
@theme static ensures --header-height is registered with Uniwind even if it is never used directly in a className. This is required for updateCSSVariables to pick it up.Uniwind.updateCSSVariables:
Brand-New Custom Utilities
Use@utility to define a class that doesnโt exist in Tailwind at all. The CSS you write inside it maps directly to React Native style properties.
Example: card-shadow
global.css
Custom utility names must be kebab-case. Tailwind scans your source files for them at build time, so the same dynamic class name rules apply โ always write the full class name in source.
Overriding Existing Tailwind Utilities
Override via @theme โ change values only
The most common approach: keep the utility name but change what value it resolves to. This works for any design token in Tailwindโs scale.
global.css
p-4, px-4, py-4, rounded-lg, etc.) update automatically โ no need to touch individual class definitions.
Override via @utility โ replace the generated CSS
Use @utility when you want to completely change what a class does, not just adjust its value.
Example: make border always use --color-primary
By default, border only sets border-width and border-style. Override it to also lock in the border color:
global.css
border always renders with the primary color instead of default value (black).
Best Practices
Related
Global CSS
Full reference for @theme, @utility, and global.css structure
updateCSSVariables
Inject CSS variable values at runtime
useCSSVariable
Read CSS variable values in JavaScript