Tailwind v4 color tokens: from Paletter to production in 60 seconds

March 2026 · 5 min read

Tailwind v4 changed how you define colors. No more JavaScript config. No more tailwind.config.js with a nested colors object that grows until nobody can read it. Now it's CSS-first. A @theme block in your stylesheet. Clean, portable, and exactly what a design token workflow needs.

Paletter exports directly into that format. Generate a palette, hit export, paste the output into your CSS file. You're done. Here's the full workflow.

The old way was painful

Tailwind v3 and earlier made you define colors in tailwind.config.js. A JavaScript object. Nested under theme.extend.colors. It looked like this:

// tailwind.config.js (v3)
module.exports = {
  theme: {
    extend: {
      colors: {
        background: '#FAF7F2',
        ink: '#1A1A1A',
        accent: '#E8C547',
        support: '#7A7A6E',
        neutral: '#D4CFC6',
      }
    }
  }
}

It worked. But it was a build-step dependency. You couldn't share it without sharing a JS file. You couldn't use it outside of Tailwind. And every time you changed a color, you had to restart the dev server.

The v4 way: CSS-first

Tailwind v4 introduced @theme blocks. You define your design tokens directly in CSS. No JavaScript. No config file. Just your stylesheet.

@theme {
  --color-background: #FAF7F2;
  --color-ink: #1A1A1A;
  --color-accent: #E8C547;
  --color-support: #7A7A6E;
  --color-neutral: #D4CFC6;
}

That's it. Tailwind picks these up and generates utility classes automatically. You get bg-background, text-ink, border-accent — all from five lines of CSS.

No build step to configure. No config file to maintain. The tokens live where CSS lives. As it should be.

From Paletter to production

Here's the 60-second workflow.

Step 1: Generate your palette

Upload a cover image or pick an inspiration palette on Paletter. The system extracts five curated colors with assigned roles: Background, Ink, Accent, Support, and Neutral.

Step 2: Export as Tailwind v4

Go to the Export tab. Select Tailwind v4. Paletter generates the @theme block with semantic names that match your palette roles. Copy it.

Step 3: Paste into your CSS

Open your main stylesheet — usually app.css or global.css. Paste the @theme block at the top, right after your Tailwind import. Save. Done.

@import 'tailwindcss';

@theme {
  --color-background: #FAF7F2;
  --color-ink: #1A1A1A;
  --color-accent: #E8C547;
  --color-support: #7A7A6E;
  --color-neutral: #D4CFC6;
}

Use it in components

Once your @theme block is in place, the semantic classes are available everywhere. No configuration. No imports. Just use them.

<header class="bg-background border-b border-support">
  <nav class="text-ink">
    <a href="/" class="hover:text-accent">Home</a>
  </nav>
</header>

<main class="bg-background text-ink">
  <h1 class="text-ink">Welcome</h1>
  <p class="text-support">Subtitle here</p>
  <button class="bg-accent text-ink border-ink">
    Get started
  </button>
</main>

Notice what's happening. Nobody reading this code needs to know what #E8C547 is. They see bg-accent and they know: that's the accent color. The class name describes intent, not appearance.

Why semantic names beat "blue-500"

Tailwind's default palette is descriptive. blue-500, gray-200, red-600. It describes what the color looks like. That's fine for prototyping. It falls apart at scale.

When you use descriptive names, your code is full of assumptions:

  • bg-blue-500 assumes your brand color is blue. Rebrand to green and you're doing a find-and-replace across every file.
  • text-gray-700 assumes that specific gray is right for body text. Change your background and every text color needs re-evaluation.
  • border-red-500 assumes errors are red. In some design systems, they're not.

Semantic names don't have this problem. bg-background is always the background. text-ink is always the primary text color. border-accent is always the accent. Rebrand your entire app by changing five hex values. The class names don't move.

This is what Paletter's Tailwind integration gives you. Not a random set of colors — a role-based system that scales.

Going further

The @theme block supports more than flat color values. You can add tints and shades for each role. Paletter generates those too — a full scale from 50 to 900 for each color role, all derived from your base palette.

You can also export as CSS custom properties or design tokens if your stack isn't Tailwind. Same palette, same roles, different output format.

And if you're using AI coding tools, the AI Palette export gives those tools your color system in a format they actually understand. Roles, contrast ratios, usage rules — all in a single markdown file.

Generate your Tailwind palette

Five curated colors. Semantic roles. Tailwind v4 @theme block ready to paste. From photo to production in under a minute.

Generate your Tailwind palette