Tailwind CSS v4 theme() Function — Referencing Design Tokens
In this tutorial, you will learn about Tailwind CSS v4 theme() Function. We cover key concepts, practical examples, and best practices to help you master this topic.
The Tailwind CSS v4 theme() function lets you reference @theme design tokens directly in custom CSS, bridging the gap between Tailwind utilities and hand-written style rules.
What You'll Learn
You will learn how to use theme() to access colors, spacing, fonts, and other tokens in custom CSS, combine theme() with calc(), and use it in @media and @container queries.
Why It Matters
theme() ensures consistency between Tailwind utilities and hand-written CSS. DodaTech uses theme() in component @layer rules and animation keyframes to maintain token alignment.
Real-World Use
DodaZIP's custom scrollbar styles use theme() to reference spacing and color tokens, ensuring the scrollbar matches the Tailwind-themed design without hardcoding values.
flowchart LR
A[CSS-First Config] --> B[theme() Function]
B --> C[Token Access]
B --> D[calc() Math]
B --> E[Keyframes]
B --> F[Custom CSS]
style B fill:#38bdf8,stroke:#0284c7,color:#fff
style C fill:#22c55e,stroke:#16a34a,color:#fff
Basic theme() Usage
@import "tailwindcss";
@theme {
--color-brand-500: #7c3aed;
--spacing-4: 1rem;
--font-family-sans: "Inter", sans-serif;
}
/* Using theme() in custom CSS */
.custom-element {
background-color: theme(--color-brand-500);
padding: theme(--spacing-4);
font-family: theme(--font-family-sans);
}
Expected output: The custom element uses the same design tokens as Tailwind utilities. If the brand color changes in @theme, both Tailwind utilities and custom CSS update.
theme() with calc()
@theme {
--spacing-nav: 4rem;
--spacing-sidebar: 16rem;
}
/* Sidebar offset for main content */
.main-content {
margin-left: theme(--spacing-sidebar);
min-height: calc(100vh - theme(--spacing-nav));
}
/* Combined calculations */
.offset-box {
padding: calc(theme(--spacing-4) * 2);
margin-top: calc(theme(--spacing-nav) + theme(--spacing-4));
}
Expected output: theme() values work inside calc() for mathematical operations. Token changes propagate to calculated values.
theme() in Media Queries
@theme {
--breakpoint-md: 48rem;
--breakpoint-lg: 64rem;
--spacing-4: 1rem;
--spacing-8: 2rem;
}
@media (min-width: theme(--breakpoint-md)) {
.responsive-card {
padding: theme(--spacing-8);
display: grid;
grid-template-columns: 1fr 1fr;
}
}
@media (min-width: theme(--breakpoint-lg)) {
.responsive-card {
grid-template-columns: 1fr 1fr 1fr;
}
}
Expected output: Media queries use the same breakpoint tokens as Tailwind's responsive prefixes. Changing --breakpoint-md updates both @media queries and md: prefix.
theme() in @keyframes
@theme {
--color-brand-500: #7c3aed;
--color-brand-200: #ddd6fe;
--spacing-4: 1rem;
}
@keyframes pulse-brand {
0%, 100% {
box-shadow: 0 0 0 0 theme(--color-brand-500);
}
50% {
box-shadow: 0 0 0 theme(--spacing-4) theme(--color-brand-200);
}
}
.pulse-button {
animation: pulse-brand 2s infinite;
background-color: theme(--color-brand-500);
color: white;
padding: theme(--spacing-4);
}
Expected output: Keyframes use theme() for colors and spacing. When the brand palette changes, animations update automatically.
theme() with Opacity
@theme {
--color-brand-500: rgb(124 58 237 / 1);
}
/* theme() with opacity */
.faded-bg {
background-color: rgb(from theme(--color-brand-500) r g b / 0.5);
}
/* Or using the / syntax if defined properly */
```css
@theme {
--color-brand-500: rgb(var(--color-brand-500-rgb) / <alpha-value>);
}
:root {
--color-brand-500-rgb: 124 58 237;
}
.faded-bg {
background-color: rgb(from theme(--color-brand-500) r g b / 0.5);
}
Expected output: theme() can access token values and modify their opacity for custom usage.
Common Mistakes
1. Using theme() Without Dash Prefix
theme(color-brand-500) is incorrect. The dash prefix is required: theme(--color-brand-500).
2. Forgetting Parentheses in calc()
calc(100vh - theme(--spacing-nav)) is correct. calc(100vh - theme(--spacing-nav)) without the inner parentheses around the subtraction fails.
3. Using theme() in Static CSS Files
theme() only works in CSS files processed by Tailwind v4. Static CSS files without @import "tailwindcss" cannot resolve theme().
4. theme() with CSS Variables That Have Spaces
Theme values with spaces (like font-family lists) must be handled carefully: use quotes or handle as separate tokens.
5. Nesting theme() Calls
theme(--spacing-4) works. theme(theme(--custom-var)) does not. theme() does not support nesting.
Practice Questions
What does theme() do in v4? References @theme design tokens in custom CSS, returning the token value.
How do you use theme() with calc?
calc(100% - theme(--spacing-4))-- theme() provides the token value for the calculation.Can you use theme() in @media queries? Yes:
@media (min-width: theme(--breakpoint-md))uses the same breakpoint tokens.What happens when a @theme token changes? All theme() references automatically update on rebuild, keeping custom CSS in sync.
Can theme() be used with any CSS property? Yes. theme() returns the raw token value, usable in any CSS property or function.
Challenge
Create a custom CSS file that uses theme() for: a sticky header with dynamic height, responsive @media queries based on token breakpoints, a keyframe animation using brand colors, and calc() combined with spacing tokens.
FAQ
Mini Project
Create a component library stylesheet that uses theme() throughout: button styles with brand colors, card spacing from tokens, responsive breakpoints from @theme, and keyframe animations referencing theme colors.
What's Next
Now master Variants in v4 for the unified variant system. Then explore Composing Variants for complex state combinations.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro