V
Vincent Romanus
Guest
There are design decisions that come back to bite you later. Color is one of them. At the beginning, it always feels like a βlaterβ problem, βLetβs just get it working first.β Fast-forward a few months, and youβre the poor soul refactoring
Theming, the separation of visual styling from component logic, usually gets introduced after requirements scream loud enough. Light/Dark mode. Whitelabel support. Multi-tenancy. Accessibility. Take your pick.
But why wait?
If you know these things might show up down the line, thereβs zero reason not to prep for them from day one. Itβs not overengineering. Itβs laying down the tracks before the train speeds up.
Solid theming starts with a system. Not just defining
This is how you build it.
Think in roles, not colors. Not βblue,β but βInfo.β Not βgreen,β but βSuccess.β Your UI communicates states, your tokens should reflect that.
Colors have states. A button doesnβt look the same when itβs hovered, focused, disabled, or selected, and your system should reflect that.
Donβt forget backgrounds. Especially when dealing with nested layouts or UI depth, a layered token model is a must.
If your software is meant for multiple clients, especially in the B2B or SaaS world, then theming isn't just a nice-to-have. It's a hard requirement.
Every customer will want their own logo. Sure. But it wonβt stop there. The moment one of them asks for βour brand colors,β you either:
Supporting custom branding at scale means color flexibility is baked into your foundation. When each client gets their own palette, your design system must decouple style from structure.
Tokens are your scalable way forward.
If youβre halfway through a project (or deep into one) and realizing you skipped theming, donβt panic. The good news? You probably donβt need a massive refactor to get back on track. You just need to start now, and you can do it incrementally.
Start by defining your design tokens in a dedicated theme scope β usually tied to a root class like
This becomes your palette, one place to rule all styles.
And because the structure is consistent, you can now define a new theme and swap with a single class change:
Apply the tokens in your core components. Hereβs a simple button example:
Start small, pick high-traffic components like buttons and forms. Over time, your codebase will shift from brittle and hardcoded to flexible and theme-aware.
If your product is going to grow, team-wise, feature-wise, or audience-wise, theming from day one is the smarter path. Not for the hype, but for the foundation.
Start with color tokens. Think in roles and states. Stop seeing your UI as βblue on white,β and start seeing it as βPrimary on Level-0.β
Your future self will thank you. Your future clients will demand it. And letβs be honest, you wanted a Dark Mode anyway.
Continue reading...
#0FB9B1
from 17 different files because marketing decided the primary turquoise needs to be 5% darker. Lovely.Theming isnβt a luxury. Itβs hygiene.
Theming, the separation of visual styling from component logic, usually gets introduced after requirements scream loud enough. Light/Dark mode. Whitelabel support. Multi-tenancy. Accessibility. Take your pick.
But why wait?
If you know these things might show up down the line, thereβs zero reason not to prep for them from day one. Itβs not overengineering. Itβs laying down the tracks before the train speeds up.
The Practical Starting Point: Color Token Design
Solid theming starts with a system. Not just defining
--primary
and calling it a day. You need structure. Context. Semantics.This is how you build it.
Color Roles
Think in roles, not colors. Not βblue,β but βInfo.β Not βgreen,β but βSuccess.β Your UI communicates states, your tokens should reflect that.
Role | Purpose |
---|---|
Basic | Neutral foundation (e.g., form fields) |
Primary | Main interactive elements |
Info | Contextual or neutral information |
Success | Positive outcomes |
Error | Validation errors or destructive actions |
State Variants
Colors have states. A button doesnβt look the same when itβs hovered, focused, disabled, or selected, and your system should reflect that.
State | Purpose |
---|---|
Default | Standard visual |
Muted | Disabled or low priority |
Highlight | Hover/Focus state |
Strong | Active/Selected state |
Facing | Text or content on top of the color |
Elevation Levels
Donβt forget backgrounds. Especially when dealing with nested layouts or UI depth, a layered token model is a must.
Code:
--level-0: #FFFFFF; /* Default background */
--level-1: #F5F8F9; /* First level nesting */
Selling B2B? Theming Is Non-Negotiable
If your software is meant for multiple clients, especially in the B2B or SaaS world, then theming isn't just a nice-to-have. It's a hard requirement.
Every customer will want their own logo. Sure. But it wonβt stop there. The moment one of them asks for βour brand colors,β you either:
Pray theyβre close to your default palette, or
Spend an unholy amount of time building what you shouldβve started with: a theme system.
Supporting custom branding at scale means color flexibility is baked into your foundation. When each client gets their own palette, your design system must decouple style from structure.
Tokens are your scalable way forward.
Okay... But What If I Havenβt Done This Yet?
If youβre halfway through a project (or deep into one) and realizing you skipped theming, donβt panic. The good news? You probably donβt need a massive refactor to get back on track. You just need to start now, and you can do it incrementally.
Create a Theme CSS File
Start by defining your design tokens in a dedicated theme scope β usually tied to a root class like
.my-theme
or :root
.
Code:
.my-theme {
/* LEVEL */
--level-0: #ffffff;
--level-1: #f5f7f9;
/* BASIC */
--basic-default: #ffffff;
--basic-muted: #e9ecef;
--basic-highlight: #dfe3e7;
--basic-strong: #b0b8c1;
--basic-facing: #1c1e21;
/* PRIMARY */
--primary-default: #2f5aa8;
--primary-muted: #d5deef;
--primary-highlight: #4a73c2;
--primary-strong: #24488c;
--primary-facing: #ffffff;
...
}
This becomes your palette, one place to rule all styles.
And because the structure is consistent, you can now define a new theme and swap with a single class change:
Code:
.my-dark-theme {
/* LEVELS */
--level-0: #1a1a1a;
--level-1: #252525;
/* BASIC */
--basic-default: #2f2f2f;
--basic-muted: #3a3a3a;
--basic-highlight: #4c4c4c;
--basic-strong: #666666;
--basic-facing: #d0d0d0;
/* PRIMARY */
--primary-default: #f72585;
--primary-muted: #4b1e38;
--primary-highlight: #fa58aa;
--primary-strong: #ff7cb8;
--primary-facing: #e8cce0;
...
}
Refactor Styles to Use Tokens
Apply the tokens in your core components. Hereβs a simple button example:
Code:
.button-base {
background-color: var(--basic-default);
color: var(--basic-facing);
&.disabled {
background-color: var(--basic-muted);
}
&:not(.disabled) {
&:hover {
background-color: var(--basic-highlight);
}
&:active {
background-color: var(--basic-strong);
}
}
}
.button-primary {
background-color: var(--primary-default);
color: var(--primary-facing);
&.disabled {
background-color: var(--primary-muted);
}
&:not(.disabled) {
&:hover {
background-color: var(--primary-highlight);
}
&:active {
background-color: var(--primary-strong);
}
}
}
Start small, pick high-traffic components like buttons and forms. Over time, your codebase will shift from brittle and hardcoded to flexible and theme-aware.
TL;DR: Theming Isnβt a Later Decision
If your product is going to grow, team-wise, feature-wise, or audience-wise, theming from day one is the smarter path. Not for the hype, but for the foundation.
Start with color tokens. Think in roles and states. Stop seeing your UI as βblue on white,β and start seeing it as βPrimary on Level-0.β
Your future self will thank you. Your future clients will demand it. And letβs be honest, you wanted a Dark Mode anyway.
Continue reading...