•6 min read

Color Palettes I Actually Use Instead of Tailwind's Defaults

Color Palettes I Actually Use Instead of Tailwind's Defaults

I like Tailwind's color system as a design tool: having 50 shades of blue pre-named and ready to go is genuinely useful. But there's a downside: every Tailwind site uses the same 50 shades of blue. When I moved my personal projects to vanilla CSS, I didn't just lose the utility classes; I lost the crutch of a pre-built palette.

Here are the alternatives I've settled on, with actual code.

Audio Briefing
0:00 / 0:00

Uchu: The One I Keep Coming Back To

Uchu is a carefully curated palette of warm, muted colors that work well for content-heavy sites. It's available as a CSS file you can drop into any project.

:root {
  --uchu-blue: #3b82f6;
  --uchu-indigo: #6366f1;
  --uchu-amber: #f59e0b;
  --uchu-rose: #f43f5e;
  --uchu-slate: #64748b;
}

What I like about it: the colors have enough personality to not look generic, but they're muted enough to not clash with content. It's a good middle ground.

Advertisement

Flexoki: For Minimalist Projects

Flexoki is an inky, low-contrast palette designed for long-form reading. It uses warm blacks and off-whites instead of pure #000 and #fff, which reduces eye strain.

:root {
  --flexoki-black: #100f0f;
  --flexoki-paper: #fffcf0;
  --flexoki-muted: #6f6e69;
  --flexoki-accent: #205ea6;
}

I use this for my personal blog. The off-white background (#fffcf0) is noticeably more comfortable to read on than pure white, especially in dark mode.

Reasonable Colors: Accessibility First

Reasonable Colors is built from the ground up for WCAG compliance. Every color in the palette meets at least AA contrast ratios when used as text on its recommended background.

:root {
  --rc-primary: #0057b3;
  --rc-primary-bg: #e8f1fa;
  --rc-success: #1e7a1e;
  --rc-warning: #9e5d00;
  --rc-error: #c41e1e;
}

This is what I reach for on client projects where accessibility requirements are explicit. The documentation includes contrast ratios for every combination.

OKLCH: The Modern Option

If you want to generate colors programmatically instead of picking from a pre-built palette, look into OKLCH. It's a color model that maintains perceptual uniformity: meaning a 10% lightness step looks like a 10% step to the human eye, unlike HSL where the same numeric shift can look dramatically different depending on the hue. Libraries like culori or oklab.ts make this work in practice.

The One-Line Approach

If you don't want to commit to a full palette, you can get surprisingly far with just CSS custom properties based on a single primary color:

:root {
  --primary: #2563eb;
  --primary-light: oklch(from var(--primary) 0.7 0.15 h);
  --primary-dark: oklch(from var(--primary) 0.3 0.2 h);
  --surface: #fafafa;
  --text: #171717;
}

The oklch(from ...) syntax is supported in all modern browsers now (2026) and lets you derive an entire palette from one color value without manual picking.

Advertisement

You Might Also Like

Deep Dive: The Core Mechanics

When we look beneath the surface, the underlying mechanics reveal a complex interplay of systems. In modern development, understanding these mechanics is what separates a novice from an expert.

Consider this practical example:

// A comprehensive example demonstrating advanced patterns
class ServiceManager {
  constructor() {
    this.services = new Map();
    this.initialized = false;
  }

  register(name, service) {
    if (this.services.has(name)) {
      throw new Error(`Service ${name} already registered`);
    }
    this.services.set(name, service);
  }

  async initializeAll() {
    this.initialized = true;
    for (const [name, service] of this.services) {
      if (typeof service.init === 'function') {
        await service.init();
      }
    }
  }

  get(name) {
    if (!this.initialized) {
      console.warn('Accessing services before initialization');
    }
    return this.services.get(name);
  }
}

This pattern ensures that our architecture remains scalable and robust even as business requirements change. It's a fundamental approach that pays dividends in large-scale applications.

Real-world Application and Scaling

Implementing this in a production environment introduces a new set of challenges. We must account for concurrency, state management, and memory leaks.

For instance, when dealing with high-throughput systems, every micro-optimization counts. We often rely on profiling tools to identify bottlenecks that aren't apparent during local development.

The diagram above illustrates a typical deployment strategy where our application scales horizontally.

Test Your Understanding

Frequently Asked Questions

While Tailwind's default palette is mathematically consistent, thousands of modern web applications share identical zinc, slate, and indigo themes, creating visual sameness across the web. Using curated alternative palettes (like Uchu, Flexoki, or Radix Colors) or building brand-specific OKLCH color scales gives your UI distinct visual character without sacrificing contrast accessibility.
Unlike HSL (where yellow at 50% lightness looks blindingly bright while blue at 50% lightness appears dark), OKLCH is perceptually uniform. A 10% shift in OKLCH lightness corresponds to a consistent perceptual change to the human eye regardless of hue. This makes programmatic dark-mode inversions and accessible WCAG contrast calculations predictable and mathematically reliable.
Leading options include Radix Colors (designed specifically for component states: background, border, solid, hover, and accessible text across 12 steps), Reasonable Colors (an open-source accessible palette where step differences guarantee WCAG AA and AAA compliance), and IBM Carbon Design System colors.
In Tailwind CSS v4, you can define your custom theme directly in your CSS entrypoint using the @theme directive (such as --color-brand-500: oklch(0.65 0.22 260);). Tailwind automatically generates matching utility classes like bg-brand-500, text-brand-500, and border-brand-500 without requiring a JavaScript configuration file.
Both Flexoki and Nord avoid harsh pure black (#000000) and pure white (#ffffff) combinations that cause halation and visual fatigue. Flexoki uses warm paper-inspired blacks and creamy off-whites, while Nord utilizes cool muted polar blues and slates, producing lower luminance contrast that remains comfortable during extended reading sessions.
Share this article:

Stay Updated

Get the latest posts delivered straight to your inbox.

Free Developer Utilities

Free In-Browser Developer Tools

Clean AI CLI logs, build cron expressions, decode JWTs, and calculate chmod permissions offline.

Explore Tools
Advertisement