Skip to main content

89. TailwindCSS for Utility-First Styling

Status: Accepted Date: 2025-07-06

Context

We need a styling solution for our React-based mercury-dashboard. Traditional CSS approaches, like BEM or CSS-in-JS libraries (like Styled Components), have drawbacks. Writing custom CSS can be slow, lead to large CSS bundles, and make it difficult to maintain consistency. CSS-in-JS can suffer from runtime performance overhead. We want a solution that is fast, maintainable, and promotes consistency.

Decision

We will use TailwindCSS as our primary styling solution for the mercury-dashboard.

TailwindCSS is a utility-first CSS framework. Instead of writing custom CSS classes, we build designs by applying pre-existing, low-level utility classes directly in our HTML/JSX.

Example: <button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">

This approach allows us to build complex component designs without ever leaving our component files, and without writing a single line of custom CSS.

Consequences

Positive:

  • Rapid Development: Building and iterating on UI designs is extremely fast, as you are composing utilities rather than inventing CSS class names and writing rules.
  • Enforces Consistency: Designs are built from a constrained set of utilities defined in a configuration file (e.g., colors, spacing, font sizes). This makes it easy to maintain visual consistency across the entire application.
  • Tiny Production CSS Bundles: Tailwind automatically scans your code and removes all unused CSS utilities at build time, resulting in the smallest possible CSS file.
  • Component-Scoped Styling: Styles are applied directly to the elements they affect, which prevents the global scope issues and unintended side effects common with traditional CSS. HTML/JSX becomes the single source of truth for a component's structure and styling.

Negative:

  • "Ugly" HTML/Verbose Class Lists: The primary criticism of Tailwind is that it can lead to long, "ugly" class lists in the markup.
  • Initial Learning Curve: Developers need to learn the utility class names, although they are very intuitive and well-documented.
  • Requires a Build Step: Tailwind requires a build process (like PostCSS) to scan the code and generate the final CSS, which adds a step to the development setup.

Mitigation:

  • Component Abstraction: The verbosity is managed by creating reusable React components. A <Button> component will encapsulate the long class list, and developers will use <Button>Click Me</Button>, which is clean and readable. The "ugly" markup is an implementation detail of the component.
  • Excellent Tooling: The official TailwindCSS VS Code extension provides excellent autocompletion, linting, and hover-previews for classes, which makes learning and using the utilities very easy.
  • Standard in Modern Toolchains: The build step is already a standard part of any modern frontend framework like Next.js, so this does not add any real complexity to our existing setup.