← Back to Tailwind CSS Mastery
Advanced14 min read

Best Practices

Write maintainable Tailwind at scale — organization conventions, team standards, accessibility patterns, and anti-patterns to avoid.

Component Organization

Organize by feature or component type, not by file type. Colocate component styles (Tailwind classes) with component logic. A Button.tsx contains both the JSX and its Tailwind classes.

Extract to shared components when patterns repeat three or more times. Keep one-off layouts inline — not everything needs abstraction.

  • Use ui/ for design system primitives used across features
  • Feature components can compose ui/ primitives freely
  • Avoid a separate styles/ directory — classes live in components
components/
├── ui/           # Shared primitives (Button, Input, Card)
├── features/     # Feature-specific components
│   ├── auth/
│   └── dashboard/
└── layouts/      # Page layout wrappers

Class Order and Readability

Sort classes consistently with Prettier tailwindcss plugin: layout, spacing, sizing, typography, colors, effects, states. Consistent ordering makes diffs readable and classes scannable.

Break long class strings across lines aligned with JSX structure. Group related utilities on the same line: all spacing together, all colors together.

// Prettier sorts automatically:
<div class="flex items-center gap-4 px-6 py-4
  bg-white rounded-xl shadow-sm
  hover:shadow-md transition-shadow">

Team Conventions

Document decisions: when to extract components, naming conventions, color token usage, and responsive patterns. Enforce with ESLint plugin eslint-plugin-tailwindcss and PR review checklists.

Agree on a component library foundation (shadcn/ui, Headless UI) to avoid reinventing accessible patterns. Customize the foundation with your brand tokens.

// .eslintrc — tailwindcss plugin catches errors
{
  "plugins": ["tailwindcss"],
  "rules": {
    "tailwindcss/classnames-order": "warn",
    "tailwindcss/no-contradicting-classname": "error"
  }
}

Accessibility Standards

Tailwind does not automatically make UI accessible. You must add focus styles, ARIA attributes, semantic HTML, and sufficient color contrast manually.

Use sr-only for screen reader text on icon buttons. Ensure focus-visible:ring is on all interactive elements. Test with keyboard navigation and screen readers.

  • Never use outline-none without focus-visible:ring replacement
  • Color contrast must meet WCAG AA in both light and dark modes
  • Use semantic HTML elements before adding ARIA roles
<button aria-label="Close dialog"
  class="focus-visible:ring-2 focus-visible:ring-blue-500
         focus-visible:outline-none">
  <XIcon class="h-5 w-5" />
  <span class="sr-only">Close</span>
</button>

Anti-patterns to Avoid

Do not use @apply everywhere — it reintroduces CSS specificity issues. Do not build class names dynamically with template literals. Do not ignore the content config — missing classes in production is a common failure.

Avoid excessively long class strings (20+ utilities) without extraction. If a class list exceeds three lines, create a component. Do not fight Tailwind with important overrides unless integrating third-party CSS.

// Bad: dynamic class names (purged in production)
<div class={'bg-' + color + '-500'} />

// Good: complete class names
const colors = { red: 'bg-red-500', blue: 'bg-blue-500' };
<div class={colors[status]} />

Get In Touch


Ready to discuss your next project? Drop me a message.