Color Theory Is Not Enough: How We Actually Build Color Systems
Color Theory Is Not Enough: How We Actually Build Color Systems
Color Theory Is Not Enough: How We Actually Build Color Systems
Knowing the color wheel is the beginning, not the end. Real color work in product and brand design is about building systems that are flexible, accessible, and semantically meaningful across every context.
Knowing the color wheel is the beginning, not the end. Real color work in product and brand design is about building systems that are flexible, accessible, and semantically meaningful across every context.
Knowing the color wheel is the beginning, not the end. Real color work in product and brand design is about building systems that are flexible, accessible, and semantically meaningful across every context.

Color theory is one of those subjects that feels foundational until you actually try to build a production-ready color system for a complex digital product. Then you discover that the Bauhaus model, beautiful as it is, does not tell you how to handle a 48-state button component in both light and dark mode.
Over the past few years, our studio has developed a methodology for building color systems that we have refined on projects ranging from consumer apps to enterprise SaaS platforms to editorial websites. Here is what we have learned.
The first principle is separation of concerns. A color system has three layers, and conflating them is the source of most color-related design debt. The first layer is your raw palette — the complete set of hue-scale values you have access to. The second layer is your semantic tokens — values named for their purpose rather than their appearance (text-primary, surface-overlay, border-subtle). The third layer is your component tokens — values specific to individual components (button-bg-default, input-border-focus). These layers should never collapse into each other.
The second principle is that accessibility is a design constraint, not a compliance checkbox. Every color pairing in your system should be tested against WCAG contrast requirements before you fall in love with it. We use an internal tool that generates a contrast matrix for every foreground-background combination in a palette. Combinations that fail AA are flagged immediately. This is not a limitation — it is an editing tool. It forces you toward color relationships that are inherently more legible and more distinctive.
Third: build for dark mode from the start, not as an afterthought. Designers who add dark mode retroactively almost always end up with a system that is just an inverted version of light mode — and inverted light mode rarely looks good. True dark mode design requires rethinking which values carry semantic meaning in low-luminance contexts. A border that works at 20% opacity on white will disappear on a dark surface. Your elevation system needs to use subtle shifts in surface lightness rather than drop shadows. These are different design problems, and they are best solved in parallel.
Fourth: your palette needs more shades than you think. The instinct of most designers is to choose a beautiful hero color and generate five or six tints. This works for simple use cases, but it breaks quickly under the demands of a real product. We now build palettes with 12 steps per hue — following a modified version of the Radix UI scale approach — which gives us enough range to handle everything from subtle backgrounds to strong borders to rich fills to accessible text.
Finally, name your tokens with use-case semantics, not appearance descriptions. “Blue-500” is a raw palette value. “brand-primary” is a semantic token. “button-bg-hover” is a component token. The closer your naming is to visual appearance, the more brittle your system will be — because the moment you decide to change your brand color from blue to green, every “blue-“ token name becomes a lie.
Color systems are not glamorous work. They are infrastructure work. But like all good infrastructure, they are invisible when they are working well — and catastrophically visible when they are not.
Color theory is one of those subjects that feels foundational until you actually try to build a production-ready color system for a complex digital product. Then you discover that the Bauhaus model, beautiful as it is, does not tell you how to handle a 48-state button component in both light and dark mode.
Over the past few years, our studio has developed a methodology for building color systems that we have refined on projects ranging from consumer apps to enterprise SaaS platforms to editorial websites. Here is what we have learned.
The first principle is separation of concerns. A color system has three layers, and conflating them is the source of most color-related design debt. The first layer is your raw palette — the complete set of hue-scale values you have access to. The second layer is your semantic tokens — values named for their purpose rather than their appearance (text-primary, surface-overlay, border-subtle). The third layer is your component tokens — values specific to individual components (button-bg-default, input-border-focus). These layers should never collapse into each other.
The second principle is that accessibility is a design constraint, not a compliance checkbox. Every color pairing in your system should be tested against WCAG contrast requirements before you fall in love with it. We use an internal tool that generates a contrast matrix for every foreground-background combination in a palette. Combinations that fail AA are flagged immediately. This is not a limitation — it is an editing tool. It forces you toward color relationships that are inherently more legible and more distinctive.
Third: build for dark mode from the start, not as an afterthought. Designers who add dark mode retroactively almost always end up with a system that is just an inverted version of light mode — and inverted light mode rarely looks good. True dark mode design requires rethinking which values carry semantic meaning in low-luminance contexts. A border that works at 20% opacity on white will disappear on a dark surface. Your elevation system needs to use subtle shifts in surface lightness rather than drop shadows. These are different design problems, and they are best solved in parallel.
Fourth: your palette needs more shades than you think. The instinct of most designers is to choose a beautiful hero color and generate five or six tints. This works for simple use cases, but it breaks quickly under the demands of a real product. We now build palettes with 12 steps per hue — following a modified version of the Radix UI scale approach — which gives us enough range to handle everything from subtle backgrounds to strong borders to rich fills to accessible text.
Finally, name your tokens with use-case semantics, not appearance descriptions. “Blue-500” is a raw palette value. “brand-primary” is a semantic token. “button-bg-hover” is a component token. The closer your naming is to visual appearance, the more brittle your system will be — because the moment you decide to change your brand color from blue to green, every “blue-“ token name becomes a lie.
Color systems are not glamorous work. They are infrastructure work. But like all good infrastructure, they are invisible when they are working well — and catastrophically visible when they are not.
Color theory is one of those subjects that feels foundational until you actually try to build a production-ready color system for a complex digital product. Then you discover that the Bauhaus model, beautiful as it is, does not tell you how to handle a 48-state button component in both light and dark mode.
Over the past few years, our studio has developed a methodology for building color systems that we have refined on projects ranging from consumer apps to enterprise SaaS platforms to editorial websites. Here is what we have learned.
The first principle is separation of concerns. A color system has three layers, and conflating them is the source of most color-related design debt. The first layer is your raw palette — the complete set of hue-scale values you have access to. The second layer is your semantic tokens — values named for their purpose rather than their appearance (text-primary, surface-overlay, border-subtle). The third layer is your component tokens — values specific to individual components (button-bg-default, input-border-focus). These layers should never collapse into each other.
The second principle is that accessibility is a design constraint, not a compliance checkbox. Every color pairing in your system should be tested against WCAG contrast requirements before you fall in love with it. We use an internal tool that generates a contrast matrix for every foreground-background combination in a palette. Combinations that fail AA are flagged immediately. This is not a limitation — it is an editing tool. It forces you toward color relationships that are inherently more legible and more distinctive.
Third: build for dark mode from the start, not as an afterthought. Designers who add dark mode retroactively almost always end up with a system that is just an inverted version of light mode — and inverted light mode rarely looks good. True dark mode design requires rethinking which values carry semantic meaning in low-luminance contexts. A border that works at 20% opacity on white will disappear on a dark surface. Your elevation system needs to use subtle shifts in surface lightness rather than drop shadows. These are different design problems, and they are best solved in parallel.
Fourth: your palette needs more shades than you think. The instinct of most designers is to choose a beautiful hero color and generate five or six tints. This works for simple use cases, but it breaks quickly under the demands of a real product. We now build palettes with 12 steps per hue — following a modified version of the Radix UI scale approach — which gives us enough range to handle everything from subtle backgrounds to strong borders to rich fills to accessible text.
Finally, name your tokens with use-case semantics, not appearance descriptions. “Blue-500” is a raw palette value. “brand-primary” is a semantic token. “button-bg-hover” is a component token. The closer your naming is to visual appearance, the more brittle your system will be — because the moment you decide to change your brand color from blue to green, every “blue-“ token name becomes a lie.
Color systems are not glamorous work. They are infrastructure work. But like all good infrastructure, they are invisible when they are working well — and catastrophically visible when they are not.

