Arbitrary Values and Their Cost
Use bracket notation like w-[347px] for one-off values and understand the trade-off between flexibility and a potentially bloated stylesheet.
Arbitrary Values and Their Cost is a free Tailwind CSS Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Tailwind CSS Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Are Arbitrary Values
Tailwind's arbitrary value syntax lets you use any CSS value directly inside a class name using square bracket notation. Instead of being limited to Tailwind's preset scale, you can write w-[347px], text-[#1a2b3c], or grid-cols-[1fr_2fr_1fr].
This feature, enabled by the JIT engine, is one of Tailwind's most powerful capabilities. It bridges the gap between utility classes and the rare cases where a precise, off-scale value is genuinely needed.
<div class="w-[347px] h-[calc(100vh-64px)] bg-[#1a1a2e] text-[#e2e8f0]">
Arbitrary values for precise control
</div>
<div class="grid grid-cols-[1fr_2fr_1fr] gap-[22px]">
Custom grid layout with arbitrary columns
</div>Syntax Reference for Arbitrary Values
The bracket syntax works with any Tailwind utility prefix. The value inside the brackets is passed directly as the CSS value. Spaces within the value are represented by underscores (Tailwind replaces them before parsing).
For utilities that generate multiple CSS properties, only the relevant property receives the arbitrary value. For example, p-[12px] sets all four padding values to 12px, just like p-4 but with a custom value.
<!-- Width and height -->
<div class="w-[240px] h-[180px]"></div>
<!-- Custom color -->
<div class="bg-[#f0a500] text-[#2d3748]"></div>
<!-- Calc values -->
<div class="top-[calc(50%_-_24px)]"></div>
<!-- CSS variables -->
<div class="bg-[var(--primary-color)]"></div>
<!-- Custom grid -->
<div class="grid-cols-[200px_1fr_minmax(200px,_1fr)]"></div>
<!-- Spacing with custom value -->
<div class="mt-[7px] px-[18px]"></div>When to Use Arbitrary Values
Arbitrary values are appropriate in specific situations:
- Precise positioning: A tooltip that must align exactly with a reference point (
top-[3px]) - External constraints: Matching a third-party component's height or border radius
- Unique brand colors: A brand color that does not fit the Tailwind palette well (
bg-[#e63946]) - Dynamic CSS expressions:
calc,min,max, orclampvalues
They are NOT appropriate for values that belong in the design system — use theme extension for those.
<!-- Appropriate: precise positioning calculation -->
<div class="absolute top-[calc(50%_-_24px)] left-[calc(50%_-_24px)]"
aria-label="Loading">
Loading spinner centered
</div>
<!-- Appropriate: brand color not in default palette -->
<header class="bg-[#e63946] text-white">
Brand header
</header>
<!-- Inappropriate: use theme extension instead -->
<!-- <div class="w-[96px]"> Use w-24 (96px) from default scale instead! -->
<div class="w-24">Use the scale utility</div>Arbitrary Values vs Theme Extension
When a value is used in multiple places across your project, it belongs in the theme extension, not as an arbitrary value. Adding it to the theme gives it a semantic name, makes it consistent, and allows you to change it in one place.
A good rule: if you use an arbitrary value twice in different files, promote it to the theme. If it appears only once in a highly specific context, the arbitrary value is fine.
// Instead of repeating w-[347px] in 5 components:
// ❌ Scattered arbitrary values
// <div class="w-[347px]">...</div> (component A)
// <div class="w-[347px]">...</div> (component B)
// <div class="w-[347px]">...</div> (component C)
// ✅ Theme extension — one source of truth
// tailwind.config.js:
module.exports = {
theme: {
extend: {
width: {
'sidebar': '347px',
},
},
},
};
// Usage:
// <div class="w-sidebar">...</div> -- consistent and namedThe Cost of Each Arbitrary Value
Each unique arbitrary value generates a unique CSS rule. Five uses of w-[347px] in the same file only generate one CSS rule (JIT deduplicates). But w-[347px], w-[348px], and w-[349px] in different components each generate separate rules — three separate rules for values that differ by a single pixel.
This is the cost of arbitrary values: they can defeat the CSS reuse that makes utility classes efficient. Ten slightly different arbitrary widths generate ten separate rules rather than one shared utility.
/* Each generates a separate CSS rule */
.w-\[347px\] { width: 347px; }
.w-\[348px\] { width: 348px; }
.w-\[349px\] { width: 349px; }
.top-\[calc\(50\%-24px\)\] { top: calc(50% - 24px); }
.top-\[calc\(50\%-32px\)\] { top: calc(50% - 32px); }
/* Compare: the scale utilities share values across all usages */
/* .w-24 is generated once and reused wherever w-24 appears */Arbitrary Property Syntax
Beyond utility prefixes, Tailwind's JIT also supports arbitrary CSS properties using the syntax [property:value] — a square bracket containing both a CSS property name and a value separated by a colon.
This is the escape hatch for CSS properties that Tailwind does not have a utility for, like [mask-image:linear-gradient(...)], [scroll-snap-type:x_mandatory], or vendor-prefixed properties. Use it sparingly — if you find yourself using many arbitrary properties, consider adding a Tailwind plugin instead.
<!-- Arbitrary CSS property -->
<div class="[mask-image:linear-gradient(to_bottom,black,transparent)]
[scroll-snap-type:y_mandatory]
[-webkit-line-clamp:3]">
Content with non-utility CSS properties
</div>
<!-- Also works with variants -->
<div class="hover:[text-decoration:underline_wavy_red]
focus:[outline:2px_solid_blue]">
Custom hover/focus styles via arbitrary property
</div>Arbitrary Values With Variants
Arbitrary values compose fully with all variant prefixes. You can combine responsive, hover, focus, dark, and other variants with any arbitrary value — the same way standard utilities work.
This gives you the full power of Tailwind's variant system for custom values. A custom off-scale hover color, a responsive custom width, or a dark-mode arbitrary color value all work seamlessly.
<!-- Responsive arbitrary width -->
<div class="w-[240px] md:w-[320px] lg:w-[400px]">
Width changes at each breakpoint
</div>
<!-- Dark mode arbitrary color -->
<div class="bg-[#f8f9fa] dark:bg-[#1a1a2e] text-[#212529] dark:text-[#f8f9fa]">
Light/dark mode with arbitrary hex colors
</div>
<!-- Hover with arbitrary value -->
<button class="bg-[#e63946] hover:bg-[#c1121f] text-white px-4 py-2 rounded-lg">
Custom brand button
</button>Color Arbitrary Values and Opacity
When using arbitrary hex colors, you can also apply the opacity modifier with a slash: bg-[#e63946]/50 sets the background to 50% opacity. This works because the slash opacity syntax is a JIT feature that applies regardless of whether the base color is from the palette or an arbitrary value.
You can also use rgba() or hsl() functions directly inside the brackets for arbitrary opacity or color model control.
<!-- Arbitrary color with opacity modifier -->
<div class="bg-[#e63946]/50">50% opacity red</div>
<div class="bg-[#e63946]/75">75% opacity red</div>
<!-- RGB function -->
<div class="bg-[rgb(230,57,70)]">RGB red</div>
<!-- HSL function -->
<div class="bg-[hsl(353,76%,55%)]">HSL red</div>
<!-- RGBA for direct alpha control -->
<div class="bg-[rgba(230,57,70,0.5)]">RGBA with alpha</div>Escape Characters in Arbitrary Values
Some characters inside arbitrary values need to be escaped because they have meaning in CSS or HTML. In Tailwind arbitrary values, use underscores for spaces (Tailwind automatically converts them) and escape parentheses and other special characters within calc() by using underscores for spaces inside the function.
For URL values (like background images), wrap the value in single quotes: bg-[url('/img/hero.png')]. Tailwind preserves the single quotes in the generated CSS.
<!-- Underscore = space in arbitrary values -->
<div class="grid grid-cols-[200px_1fr] gap-[10px_20px]">
Column gap 10px, row gap 20px
</div>
<!-- calc with underscore-spaces -->
<div class="w-[calc(100%_-_64px)]">
Full width minus 64px
</div>
<!-- URL as background image -->
<div class="bg-[url('/img/hero.jpg')] bg-cover bg-center h-64">
Hero image
</div>Audit Your Arbitrary Values
Periodically search your codebase for all arbitrary value usages to identify candidates for theme extraction. A quick grep identifies every bracket class in your project:
Any value appearing more than twice in different files is a strong candidate for a named theme token. Any value appearing once is fine as an arbitrary value. Values that look like they belong to a consistent scale (like w-[350px], w-[360px], w-[370px]) signal that an off-scale usage pattern needs to be standardized.
# Find all arbitrary value usages in your project
grep -roh 'class="[^"]*\[[^\]]*\][^"]*"' src/ | sort | uniq -c | sort -rn
# Or more targeted: find classes with bracket notation
grep -roh '[a-z:-]*\[[^\]]*\]' src/ --include='*.{html,js,jsx,ts,tsx}' | sort | uniq -c | sort -rn
# Review high-count arbitrary values — add to theme if used 3+ timesStacking Arbitrary Values With Utilities
Arbitrary values compose naturally with standard utility classes in the same class string. You can mix scale utilities and arbitrary values freely — this is intentional, not a workaround. The design system handles 95% of cases with scale utilities; arbitrary values fill the remaining 5%.
The key discipline is using scale utilities first and reaching for arbitrary values only when the scale genuinely does not have what you need. Enforce this discipline in code review to keep your markup from becoming a collection of off-scale arbitrary values.
<!-- Mixing utilities and arbitrary values naturally -->
<div class="flex items-center gap-4 px-6 py-3 <!-- scale utilities -->
w-[480px] <!-- arbitrary: specific width -->
bg-[#1a1a2e] <!-- arbitrary: brand color -->
rounded-xl shadow-lg <!-- scale utilities again -->
text-sm font-medium text-white">
A card using both
</div>Quick Check
Test your understanding of Tailwind CSS Mastery concepts from this lesson.
Lesson Recap
In this lesson you learned: arbitrary values use [value] bracket syntax to set any CSS value on any utility, powered by JIT's on-demand generation; each unique arbitrary value generates a unique CSS rule, so repeated off-scale values across files should be promoted to the theme; and underscores represent spaces inside arbitrary values (e.g., calc(100%_-_64px)). This concludes the JIT and Production Optimization course — next we explore design tokens and systematic theming.
Frequently asked questions
Is the “Arbitrary Values and Their Cost” lesson free?
Yes — the full text of “Arbitrary Values and Their Cost” is free to read here on the web, and the Tailwind CSS Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Tailwind CSS Academy course, upgrade to CoddyKit PRO.
What will I learn in “Arbitrary Values and Their Cost”?
Use bracket notation like w-[347px] for one-off values and understand the trade-off between flexibility and a potentially bloated stylesheet. You practise Tailwind CSS Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Tailwind CSS Academy?
No prior experience is required. Tailwind CSS Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Arbitrary Values and Their Cost” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Tailwind CSS Academy lesson?
Yes. Every Tailwind CSS Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- How the JIT Engine Works
- Safe-Listing Dynamic Classes
- Analyzing and Reducing Bundle Size
- Arbitrary Values and Their Cost