Hanzla
Back to blogDesign

Mastering Tailwind CSS: From Basics to Beautiful

Advanced Tailwind techniques to build responsive, maintainable designs faster — without the CSS bloat.

2 min read

Tailwind gets a lot of flak, most of it from people who never used it past the documentation homepage. Used well, it's the fastest way to build maintainable interfaces in a team. Here's how to actually use it well.

Stop fighting the abstraction#

The single biggest mistake with Tailwind is trying to bend it back into traditional CSS. Don't.

// Don't do this
<div className="card">...</div>
// styles.css: .card { @apply rounded-lg shadow-md p-4; }
 
// Do this
<div className="rounded-lg shadow-md p-4">...</div>

When you reach for @apply, you've reinvented BEM. The whole point is that the styles travel with the markup.

Componentize, don't classify#

When utility lists get long, the answer isn't a CSS class. It's a component.

function Card({ children }: { children: React.ReactNode }) {
  return (
    <div className="rounded-lg border border-zinc-800 bg-zinc-900 p-6 hover:border-zinc-700 transition-colors">
      {children}
    </div>
  )
}

Now reuse <Card> everywhere. The class list is irrelevant — the component is the unit of reuse.

Theming with CSS variables#

For dark mode and design tokens, use CSS variables in your Tailwind config:

// tailwind.config.ts
colors: {
  surface: 'rgb(var(--surface) / <alpha-value>)',
}
:root { --surface: 250 250 250; }
.dark { --surface: 10 10 10; }

This pattern lets you swap themes with a single class change anywhere in the tree.

Tip

The <alpha-value> token is what makes bg-surface/50 work. Don't skip it.

Arbitrary values, sparingly#

w-[37.5%] works. But if you find yourself writing arbitrary values often, your design tokens are wrong. Add the value to your config:

spacing: {
  '4.5': '1.125rem',
}

Now p-4.5 works everywhere and stays consistent across the codebase.

The bottom line#

Tailwind is a discipline, not a shortcut. Learn the tokens, build component primitives, lean into the constraints. The result is interfaces that are fast to write and easy to change.

Share:

Subscribe to the newsletter

Get an email whenever I publish a new post. No spam, unsubscribe anytime.

Comments

Share your thoughts. Your email is private and won't be displayed.

Loading comments…