paletteEngineering

Styling & Tailwind

Utility-first styling, design tokens, composing variants, responsive and dark mode, keeping class soup readable.

1 item

Links1

01NotesNote

Why utility-first works

Tailwind keeps styles co-located with markup, eliminates the naming problem (no more .card__header--active), and ships only the classes you actually use. No context-switching to a separate CSS file, no dead styles piling up. The trade-off is verbose className strings — manage that with extraction, not by abandoning the approach.

Design tokens are the foundation

  • Define your palette, spacing, fonts, and radii in the theme config (or CSS variables in v4). Then use bg-brand, text-muted, rounded-card — semantic tokens, not raw hex values scattered through components.
  • This is what makes a redesign a config change instead of a find-and-replace. Tie tokens to your actual brand (e.g. the #0066cc blue), not Tailwind's defaults.

Taming long class lists

  • Extract a component, not a CSS class. Repeated button markup → a <Button> component with variants. This is the React-native answer to "I'm repeating classes."
  • For variant logic, use cva (class-variance-authority) or tailwind-merge to compose conditional classes cleanly and resolve conflicts (so a later px-4 correctly overrides an earlier px-2).
  • Keep conditional classes readable with a clsx/cn helper rather than template-string spaghetti.

Responsive & dark mode

  • Mobile-first: unprefixed = base, then sm: md: lg: layer up. Design the small screen first, enhance upward.
  • Dark mode via the dark: variant. Drive it off a class strategy so you can toggle it with a theme switch, and define both light and dark token values once.

When to drop to raw CSS

  • Complex keyframe animations, very specific one-off layouts, or @supports queries can be cleaner in a small CSS file or a <style>. Tailwind isn't dogma — use plain CSS where it's genuinely clearer.

Consistency beats cleverness

  • Pick spacing/size scales and stick to them. The value of a design system is the constraint. Use a UI primitive layer (Radix + Tailwind, or shadcn/ui) for accessible, consistent building blocks instead of hand-rolling every dropdown and dialog.