Fityra/Blog
ArticlesBuild in PublicDeep Divesfityra.app ↗
Fityra/Blog

Technical deep dives and lessons learned building the Fityra ecosystem.

RSSSitemap

Blog

  • All Articles
  • Build in Public
  • Technical Deep Dives
  • Product Updates

Ecosystem

  • fityra.app ↗
  • SaaSLift ↗
  • Extensions ↗

© 2026 Edson Mark. All rights reserved.

Design Tools

How to Turn a Website Color Palette Into Design Tokens

A practical guide to turning extracted website colors into reusable design tokens for CSS variables, Tailwind themes, UI systems, and landing pages.

8 min read
design tokenscolor palettecolor scheme extractorcss variablestailwind cssweb designui designlanding pages
How to Turn a Website Color Palette Into Design Tokens

How to Turn a Website Color Palette Into Design Tokens

A color palette is useful for about five minutes.

Design tokens are useful for the whole project.

That difference took me longer to learn than I want to admit.

When I first started studying website colors, I was happy just to collect hex codes. I would see a clean landing page, inspect the colors, copy a blue, a gray, a white, maybe an accent, and then paste them into my own project.

It felt productive.

But then the real work started.

Which color should be the button?

Which gray is for borders?

Which color is body text?

Which one is muted text?

Should this pale background be used for cards, sections, or selected states?

Where does the accent belong?

That is when I realized raw colors are not a system. They are just materials.

A design token gives a color a job.

That is why I added token output to Color Scheme Extractor. Extracting a palette is the first step. Turning that palette into reusable names is what makes it useful inside a real product.

This is how I think about it now.

A palette tells you what exists

A website palette is a list of colors used on a page.

It might look like this:

#FFFFFF
#0A2540
#635BFF
#00D4FF
#F6F9FC
#1A1F36
#DF1B41

That list is not bad.

It tells you what exists.

But it does not tell you what anything is for.

You can guess, of course. Maybe #635BFF is the primary color. Maybe #0A2540 is a heading color. Maybe #F6F9FC is a surface color. Maybe #00D4FF is an accent.

But if you keep using raw hex values directly in your UI, the project slowly becomes messy.

You end up with code like this:

.button {
  background: #635BFF;
  color: #FFFFFF;
}
 
.card {
  border: 1px solid #F6F9FC;
}
 
.heading {
  color: #0A2540;
}

At first, this feels fine.

Then the design changes.

The button color needs to be darker. The border is too weak. The heading color is reused in twenty places. The accent color is scattered across components. You search for hex values, replace one, miss another, and now the UI has tiny inconsistencies everywhere.

That is the pain design tokens solve.

A token tells you what a color does

A design token is a named design decision.

For color, it might look like this:

:root {
  --background: #FFFFFF;
  --surface: #F6F9FC;
  --text: #1A1F36;
  --heading: #0A2540;
  --primary: #635BFF;
  --accent: #00D4FF;
  --danger: #DF1B41;
}

Now the colors have roles.

Instead of asking, "where did I use #635BFF?" you ask, "where did I use --primary?"

That is a better question.

The token name becomes a small piece of product thinking. It says this color is not just purple-blue. It is the primary action color. This one is not just dark navy. It is the heading color. This one is not just pale gray. It is the surface color.

That makes the system easier to use, easier to change, and easier to explain.

The first mistake: naming tokens by appearance

When people start with tokens, they often name colors by what they look like.

:root {
  --blue: #635BFF;
  --dark-blue: #0A2540;
  --light-gray: #F6F9FC;
  --red: #DF1B41;
}

This is better than random hex values, but it still has a problem.

Appearance-based names do not explain usage.

What happens if --blue becomes green after a brand refresh?

What happens if --light-gray is used as a section background in one place, a card background in another, and a border in another?

What happens when the same blue is sometimes a link, sometimes a button, sometimes a badge, and sometimes decoration?

The naming starts to break.

That is why I prefer role-based names for product UI:

:root {
  --background: #FFFFFF;
  --surface: #F6F9FC;
  --foreground: #1A1F36;
  --heading: #0A2540;
  --primary: #635BFF;
  --primary-foreground: #FFFFFF;
  --accent: #00D4FF;
  --danger: #DF1B41;
}

These names describe jobs, not colors.

That gives you more freedom later.

The second mistake: making too many tokens too early

The opposite mistake is creating a huge token system before the product needs it.

I have done this too.

You start with one landing page and suddenly you have:

--primary-50
--primary-100
--primary-200
--primary-300
--primary-400
--primary-500
--primary-600
--primary-700
--primary-800
--primary-900

Then the same for gray, blue, teal, red, yellow, and every possible state.

That can be useful in a mature design system.

But for a small product, it can be too much.

When I am building a landing page or a small tool, I start with fewer tokens:

:root {
  --background: #F8FAFC;
  --surface: #FFFFFF;
  --surface-muted: #EEF6F5;
  --text: #101828;
  --text-muted: #667085;
  --border: #D9E2E7;
  --primary: #2F6FED;
  --primary-hover: #255FD1;
  --primary-foreground: #FFFFFF;
  --accent: #15A99A;
  --warning: #F4B740;
}

That is enough to build a lot of real UI:

  • page background
  • cards
  • sections
  • headings
  • paragraphs
  • borders
  • buttons
  • hover states
  • accents
  • warnings

Small systems are easier to keep consistent.

You can always add more tokens when the product earns them.

How I turn an extracted palette into tokens

When I extract a palette from a website, I do not convert every color into a token.

I sort first.

I ask:

  • Which color covers the most space?
  • Which color is used for text?
  • Which color is used for headings?
  • Which color is used for actions?
  • Which color is used for secondary surfaces?
  • Which color is used for borders?
  • Which colors are accents, states, or decoration?

Then I create tokens from the important roles.

A typical mapping looks like this:

Most common light color -> --background or --surface
Darkest readable color -> --text or --heading
Strong brand color -> --primary
Pale brand tint -> --primary-soft or --surface-muted
Quiet divider color -> --border
Secondary readable gray -> --text-muted
Warm attention color -> --warning
Red state color -> --danger

This is the part where judgment matters.

A tool can help identify candidates, but you still decide what each color should mean in your project.

That decision is where design starts.

Example: from raw palette to CSS variables

Imagine Color Scheme Extractor gives you a palette like this:

#FFFFFF
#F6F9FC
#0A2540
#1A1F36
#635BFF
#00D4FF
#DF1B41
#E6EBF1

A raw copy-paste approach would use those values wherever they feel right.

A token approach turns them into roles:

:root {
  --background: #FFFFFF;
  --surface: #F6F9FC;
  --heading: #0A2540;
  --text: #1A1F36;
  --primary: #635BFF;
  --accent: #00D4FF;
  --danger: #DF1B41;
  --border: #E6EBF1;
}

Now you can build components with meaning:

.hero {
  background: var(--background);
  color: var(--text);
}
 
.hero h1 {
  color: var(--heading);
}
 
.button-primary {
  background: var(--primary);
  color: white;
}
 
.card {
  background: var(--surface);
  border: 1px solid var(--border);
}

This makes the UI easier to reason about.

If the primary color changes, the button system changes. If the border color changes, every card can update together. If the text color is too harsh, you adjust one token instead of chasing values across files.

Example: turning tokens into Tailwind colors

If I am using Tailwind, I still think in tokens.

One approach is to expose CSS variables and reference them in Tailwind:

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        background: 'var(--background)',
        surface: 'var(--surface)',
        text: 'var(--text)',
        muted: 'var(--text-muted)',
        border: 'var(--border)',
        primary: 'var(--primary)',
        accent: 'var(--accent)',
        danger: 'var(--danger)',
      },
    },
  },
}

Then the markup starts reading like a design system:

<section class="bg-background text-text">
  <div class="rounded-lg border border-border bg-surface">
    <h2 class="text-text">Launch faster</h2>
    <p class="text-muted">Use colors consistently across the page.</p>
    <button class="bg-primary text-white">Get started</button>
  </div>
</section>

That is much easier to maintain than random hex values.

It also makes your UI language visible in the code. You can tell what each color is supposed to do without opening a design file.

Why tokens make landing pages better

Landing pages seem simple until you build a real one.

A page needs many small color decisions:

  • hero background
  • navigation links
  • CTA button
  • secondary button
  • screenshot frame
  • card backgrounds
  • feature icons
  • muted descriptions
  • pricing border
  • FAQ dividers
  • footer text

If each decision is made separately, the page starts to drift.

One section uses a slightly different gray. Another uses a stronger border. One button has a hover state that does not match. The footer text is too faint. The badges use colors that feel unrelated.

Tokens prevent drift.

They give every section the same source of truth.

That does not make the page boring. It makes the page coherent.

Once the system is stable, you can still add emphasis. You just add it intentionally.

Tokens also make accessibility easier

Contrast is easier to manage when colors have roles.

If you use raw values everywhere, you have to check every random pair.

If you use tokens, you can focus on the important pairs:

--text on --background
--text-muted on --background
--text on --surface
--primary-foreground on --primary
--danger on --background
--warning text on --warning background

This is one reason I connect tokens and accessibility in my own workflow.

A token is not complete until I know where it is allowed to be used.

For example:

--accent may be fine for icons.
--accent may not be strong enough for paragraph text.
--warning may need dark text instead of white text.
--text-muted may work for metadata but not long body copy.

This turns accessibility from a final audit into a design constraint you can apply while building.

That is much healthier.

How Color Scheme Extractor helps with this

The tokens feature in Color Scheme Extractor exists because I wanted the tool to go beyond swatches.

A list of colors is interesting.

A set of generated tokens is actionable.

When the extension identifies common roles like primary, heading, background, surface, text, accent, and error, it gives you a starting point. You can copy the output into CSS variables, Tailwind config, JSON, or whatever format fits your workflow.

You still need judgment.

But the boring translation step becomes faster.

Instead of starting with an empty file, you start with a draft system.

That is useful when you are building alone and trying to keep momentum.

My simple token naming rules

These are the rules I use most often.

Name by role first

Use --primary, --background, --surface, --text, and --border before using names like --blue or --gray.

Role names survive redesigns better.

Keep tokens boring

A token system is not the place to be clever.

Boring names are easier to remember and easier to use.

Add states only when needed

Do not create --primary-hover, --primary-active, and --primary-disabled until the UI actually needs them.

Start small.

Separate text and background tokens

Do not assume a color that works as a background also works as text.

Give foreground colors their own names.

Make contrast part of the token decision

A token should not only look right. It should work in its intended role.

If --primary cannot support readable button text, adjust it or create a better foreground token.

A practical starter token set

If you do not know where to begin, this is enough for most landing pages:

:root {
  --background: #F8FAFC;
  --surface: #FFFFFF;
  --surface-muted: #F1F5F9;
 
  --text: #0F172A;
  --text-muted: #64748B;
 
  --border: #E2E8F0;
 
  --primary: #2563EB;
  --primary-hover: #1D4ED8;
  --primary-foreground: #FFFFFF;
 
  --accent: #14B8A6;
  --accent-soft: #CCFBF1;
 
  --danger: #DC2626;
  --warning: #F59E0B;
}

You can build a lot with this.

Then, as your product grows, you can add more specific tokens:

:root {
  --card: var(--surface);
  --card-border: var(--border);
  --nav-link: var(--text-muted);
  --nav-link-active: var(--text);
  --badge-background: var(--accent-soft);
  --badge-text: #0F766E;
}

The second layer is more semantic. It maps your base colors to specific components.

That is useful when the product becomes more complex.

The moment tokens start paying off

Tokens feel like extra work until the first change.

Then they pay for themselves.

A landing page might start with a blue primary color. Later, you decide teal fits the product better. If the page uses raw hex values, you hunt through files.

If the page uses tokens, you update one value:

:root {
  --primary: #0F766E;
  --primary-hover: #115E59;
}

The product shifts without a full redesign.

That is the quiet power of tokens.

They let you change direction without tearing the interface apart.

The final lesson

A website color palette is inspiration.

Design tokens are infrastructure.

That sounds a little dramatic, but it is true in practice. Tokens turn visual taste into repeatable decisions. They help you build faster, stay consistent, check contrast earlier, and avoid random color drift across your UI.

That is why I do not stop at extracting colors anymore.

I ask what each color is supposed to do.

Then I name it.

Once a color has a name, it becomes part of the system.

And once you have a system, building feels less like guessing.

Share
PreviousWhy Color Contrast Matters More Than the Palette ItselfNextHow to Export a Website Color Palette Into CSS, Tailwind, and JSON

Related articles

How to Build a Landing Page Color System Without Starting From Scratch
Design Toolslanding page color systemcolor palette

How to Build a Landing Page Color System Without Starting From Scratch

How to Build a Landing Page Color System Without Starting From Scratch The hardest part of choosing landing page colors is not finding a nice color. It is building a system that still works after the hero section. I have made this mistake more than once. I pick a good primary color, drop it into a button, maybe add a...

6 min readRead more
How to Export a Website Color Palette Into CSS, Tailwind, and JSON
Design Toolscolor palette exportcss variables

How to Export a Website Color Palette Into CSS, Tailwind, and JSON

How to Export a Website Color Palette Into CSS, Tailwind, and JSON Exporting colors sounds simple until you actually try to use the colors in a real project. A palette on its own is just inspiration. A copied export is where it starts becoming useful. That is the reason I cared so much about the export flow in Color...

7 min readRead more
How I Use Color Scheme Extractor When Building Landing Pages
Design Toolscolor scheme extractorlanding pages

How I Use Color Scheme Extractor When Building Landing Pages

How I Use Color Scheme Extractor When Building Landing Pages There is a specific moment in almost every landing page build where I start doubting the colors. The layout is working. The copy is close. The buttons are in the right place. The product screenshot is sitting there politely, waiting for the page around it to...

10 min readRead more

On this page

  • A palette tells you what exists
  • A token tells you what a color does
  • The first mistake: naming tokens by appearance
  • The second mistake: making too many tokens too early
  • How I turn an extracted palette into tokens
  • Example: from raw palette to CSS variables
  • Example: turning tokens into Tailwind colors
  • Why tokens make landing pages better
  • Tokens also make accessibility easier
  • How Color Scheme Extractor helps with this
  • My simple token naming rules
  • Name by role first
  • Keep tokens boring
  • Add states only when needed
  • Separate text and background tokens
  • Make contrast part of the token decision
  • A practical starter token set
  • The moment tokens start paying off
  • The final lesson