Tailwind CSS Content Globs and Arbitrary Values: Practical Engineering Decisions
When Tailwind styles vanish in production or dev builds slow, the usual suspects are content glob configuration and arbitrary value usage. This post explains the mechanics and offers concrete audit strategies.
12 Nov 2025, 13:35 UTC

The Content-Scanning Gap in Large Tailwind Projects
In a monorepo with dozens of component libraries and shared UI kits, Tailwind CSS styles can quietly disappear in production. The root cause is rarely a syntax error; it is usually a mismatch between the framework's Just-In-Time scanner and the actual files that emit class names.
How JIT Content Scanning Works
Tailwind's JIT engine relies on a content configuration—content in v3 or @source in v4—to determine which files to parse for utility class strings. If a component lives in src/components/ui/Alert.tsx but the glob only matches ./src/**/*.{js,jsx}, the TSX file is never scanned, and any Tailwind classes used inside it are omitted from the final CSS.
To avoid this, include all relevant extensions and directory depths in your glob. A practical pattern is content: ./src/**/*.{js,jsx,ts,tsx,vue,svelte} or using pattern libraries that auto-detect. Excluding node_modules and build artifacts is equally important; scanning those directories adds thousands of irrelevant files and noticeably slows dev server startup.
Arbitrary Values: Expressiveness Versus Bundle Impact
Tailwind supports arbitrary values via square-bracket syntax, such as w-[123px] or bg-[#123abc]. This is useful for one-off layouts that fall outside your design token scale. However, when arbitrary values appear across many components, each unique value generates a distinct CSS rule, which can inflate the production bundle and erode design consistency.
| Approach | Benefit | Risk |
|---|---|---|
Theme tokens (e.g., p-4) | Single source of truth, easy global updates | Less flexible for edge-case spacing |
Arbitrary values (e.g., p-[17px]) | Pixel-perfect control without config changes | CSS bloat and "magic numbers" scattered in code |
A practical middle ground is to extend the theme scale for commonly needed edge values, or use a mapping object in JavaScript/TSX to keep class strings literal:
const spacingMap = {
tiny: 'p-1',
compact: 'p-2',
custom: 'p-6',
};This keeps the generated CSS deterministic while avoiding raw numeric literals in your markup.
Verifying and Auditing Your Configuration
- Run a production build:
npm run build(ornpx tailwindcss -i src/input.css -o dist/output.css --minify) - Search the output CSS for a known utility, e.g.,
text-red-600. If it's missing despite being used in your UI, a content path is likely absent. - Add a new template file with a distinctive class, watch the dev server rebuild, and confirm the style appears without a manual restart.
- Audit your content globs against your actual source tree, including all framework-specific extensions (.tsx, .vue, .svelte) and any non-standard file locations.
These steps catch the most common scanning gaps before they reach deployment.
Closing Thoughts
Tailwind CSS gives you powerful levers, JIT compilation, arbitrary values, and flexible content scanning, but each comes with measurable trade-offs. By treating content globs as a first-class configuration item and favoring theme-scale extensions over broad arbitrary value usage, teams can keep builds fast, CSS bundles small, and UIs consistent across large codebases.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.