Taming Tailwind

A Frontend Developer's Journey Through Design Tokens & Dark Mode

In this post, I walk through some of the surprisingly hard-won lessons I encountered while building a portfolio site using React, Next.js, and Tailwind CSS — including real examples where things broke, and how I fixed them.


Goal

Build an elegant, expressive, and accessible site with:

  • Clean vertical navigation
  • Rotated typography
  • Dark/light theme switching
  • Design tokens via :root
  • Typographic flair and polish

1. When Tailwind Surprises You

Real-Life Problem

I wanted a simple left border to highlight the active vertical nav item:

<Link
  href="/blog"
  className="border-l-2 pl-2 text-black dark:text-white border-black dark:border-white"
>
  BLOG
</Link>

What Went Wrong

In light mode, it rendered as a black box instead of a thin line.

In dark mode, it looked correct.

Backgrounds and paddings were colliding silently.

The Fix

I removed Tailwind’s border-* classes entirely and used inline styles:

<Link
  href="/blog"
  style={{
    borderLeft: "2px solid",
    borderColor: theme === "dark" ? "white" : "black",
  }}
>
  BLOG
</Link>

Later, I abstracted borderColor to a CSS variable: --border-active.


2. Dark Mode Tokens: Avoid dark :root

Real-Life Problem

I wrote:

.dark :root {
  --foreground: #fefefe;
}

And it didn’t work at all.

The Fix

Use .dark directly:

:root {
  --foreground: #111;
}

.dark {
  --foreground: #fefefe;
}

When <html class="dark"> toggles, the override works as intended.


3. When Typography Leaks Downstream

Real-Life Problem

My project hover details (like tech stacks) looked scrunched and unreadable.

The parent <nav> used a huge custom class:

<nav className="text-display-title serif">

The Fix

Reset typography inside the hover child:

<div className="text-xs font-sans not-italic leading-snug tracking-normal text-foreground">
  React · TypeScript · Tailwind
</div>

4. Put Design Tokens Where They Belong

What Worked

All tokens live in global.css:

:root {
  --background: #1e1b2e;
  --foreground: #f6f1e7;
}

.dark {
  --background: #0c0c0c;
  --foreground: #fefefe;
}

Then map them into Tailwind:

colors: {
  background: 'var(--background)',
  foreground: 'var(--foreground)',
}

This made dark mode, theming, and visual consistency simple and reliable.


🧹 Final Thoughts

Tailwind isn’t stubborn; it just asks you to understand where its abstractions end.

In those boundary zones — between utilities, raw CSS, and design tokens — you can craft something both expressive and resilient.

Code that breathes a little easier.