Best Practices & Anti-Patterns
When to Use
Reference before code review, architecture decisions, or when evaluating whether a Tailwind implementation is idiomatic.
Core Philosophy
Utility-first means utilities are the default, and abstractions are earned through genuine reuse. Write utilities in markup until a real pattern emerges across multiple files.
Development Standards
| Practice | Do | Don't |
|---|---|---|
| Class organization | Layout → sizing → spacing → typography → color → effects → state | Random order |
| Token usage | All colors/sizes from @theme tokens |
Raw hex values in reusable components |
| Responsive | Mobile-first with sm:, md: prefixes |
Desktop-first with max-* as primary |
| Focus styles | focus-visible: for keyboard rings |
focus: or bare outline-none |
| Dynamic values | Static class lookup maps | String interpolation (bg-${color}-500) |
Anti-Patterns
-
Recreating Bootstrap with @apply —
@applycompiles utilities back into CSS. When a color changes, you update the token AND hunt down every@applyreference. Use framework components instead. -
Fighting the spacing scale — Using
p-[13px]consistently signals a mismatch between design and the token system. Fix the token, not the utility. -
Inconsistent color references — Mixing
bg-blue-500,bg-[#3b82f6], andbg-primaryfor the same color. Pick the token and use it everywhere. -
Ignoring the extraction signal — Copy-pasting 8+ utility classes across files more than twice = create a framework component. The markup IS the component contract.
-
Arbitrary values for design system values —
w-[340px]used consistently means340pxbelongs in@theme. Arbitrary values are for truly one-off cases. -
Overloading @layer components — 20+ classes in
@layer componentsmeans you've rebuilt Bootstrap. Step back; these should be framework components or inline utilities.
Security Standards
- Never build Tailwind class names from user input —
bg-${userColorPreference}-500creates a surface where users can influence what CSS is generated or cached. - Sanitize class attributes — if user-provided data renders as CSS class attributes in HTML, sanitize it; non-existent class names can be used for CSS injection.
- Validate token values from APIs or CMS — malformed oklch values won't cause XSS but may break rendering.
Performance Standards
- Avoid safelisting entire color scales when you only need 3 shades —
@source inlinegenerates CSS at build time. - Tailwind's output is already tree-shaken; the developer cost is class-name verbosity, not runtime performance.
@containeradds no JavaScript; it's pure CSS.- Prefer
transition-colors duration-200over JS-driven class toggling for simple state changes.
Common Mistakes
- Wrong: Using Tailwind like a utility-class version of Bootstrap — the mental model is wrong; utilities are composable primitives. Right: Write markup-first, extract only when duplication is proven.
- Wrong: Starting with component extraction before seeing real duplication — YAGNI applies.
- Wrong: Defining
--color-brand-150in@themebut never usingbg-brand-150. Right: Over-configured tokens add dead weight.
See Also
- Accessibility
- Performance Optimization
- @apply Guidance
- Reference: https://www.faraazcodes.com/blog/tailwind-2025-best-practices