Branding

Building a Brand Palette: From Hex Code to Design System

By ColorStudio · August 10, 2026 · 6 min read

A brand palette is not a swatch grid — it is a contract. It is the set of color decisions a team agrees to use consistently, across every screen, every component, and every marketing surface, so that the product looks like one thing instead of many. The hard part is not picking a color; the hard part is turning that color into a system that scales. This article walks the process from the first decision — what should the brand feel like — to the last: documenting the palette so a developer, a designer, and a marketer all reach for the same value.

Starting with Brand Personality

Before any hex code, answer one question: what should the brand feel like? A fintech app needs to feel trustworthy and precise, which points toward blue, green, and restrained saturation. A children's learning platform needs to feel playful and warm, which points toward saturated primaries and high lightness. A luxury beauty brand needs to feel premium and calm, which points toward deep or desaturated hues with low chroma.

Personality narrows the hue space before you pick a single color. Write it down in three or four adjectives — "calm, competent, modern" or "energetic, friendly, affordable" — because every later decision gets checked against those words. If a candidate color does not match the personality, it does not go in the palette, no matter how good it looks in isolation.

Choosing a Primary Color

The primary color is the brand color. It is the one that appears in the logo, the buttons, the links, and the accent surfaces — the color a user would name if asked "what color is this app?" There should be exactly one, and it should be the strongest expression of the brand personality.

Pick the primary first, and pick it at a single specific hex code, not a range. Test it against three things: it must pass WCAG AA contrast (4.5:1) when used as text on white, it must pass 3:1 when used as a button background with white text, and it must look correct on both light and dark backgrounds. If the primary fails any of these, adjust the hue's lightness or saturation until it passes. A primary that cannot be used for text or buttons is not a primary — it is an accent pretending to be one.

Building Tints and Shades (50–900 Scale)

One hex code is not a palette; it is a seed. The next step is to generate a lightness ramp from that primary, typically on a 50–900 scale where 50 is near-white, 500 is the base primary, and 900 is near-black. This is the scale that Tailwind, Material Design, and most design systems use, because it gives every component a consistent set of options: a 100 for subtle backgrounds, a 600 for hover states, a 700 for pressed states, and so on.

The ramp is generated by interpolating between the base hue and white (for tints, 50–400) and between the base hue and black (for shades, 600–900). The key is to hold the hue constant and shift only lightness, with a gentle reduction in saturation as colors get very dark or very light — fully saturated near-white and near-black colors look unnatural. The 500 step is the brand primary, defined exactly; every other step is a lightness variation of it. Test the ramp by placing swatches side by side and checking that the progression is even — if one step jumps too far in lightness, it will look like a gap in the interface.

Adding Secondary and Accent Colors

Most brands need one or two colors beyond the primary. These are the secondary and accent, and they exist to do jobs the primary cannot:

  • Secondary. A supporting color, usually analogous or complementary to the primary, used for secondary buttons, info states, illustrations, and large surfaces that should not compete with the primary. A blue primary often pairs with a teal secondary (analogous) or an orange secondary (complementary).
  • Accent. A high-saturation color used sparingly for attention: a notification badge, a highlighted metric, a sale tag. The accent is the 10% in the 60-30-10 rule, and it should contrast strongly with both the primary and the neutrals so it cannot be mistaken for either.
  • Semantic colors. Success (green), warning (yellow or orange), error (red), and info (blue) are functional, not decorative. Define them once, use them only for their function, and never let them overlap with the brand palette — if your primary is green, your success state needs to be a different green or your success messages will read as "branded" instead of "successful."

Neutral Colors for Text and Backgrounds

Neutrals are the most-used colors in any interface and the most overlooked. Every body text, every background, every border, every disabled state is a neutral, and if the neutral ramp is off, the whole interface feels wrong even when the brand colors are perfect.

Build a neutral ramp with a slight tint of the primary hue — a blue primary gets cool-gray neutrals, a warm primary gets warm-gray neutrals. Pure gray (no hue tint) reads as cold and inert. The ramp needs at least five steps: a near-white background, a subtle surface (for cards), a border, a muted text, and a near-black body text. Check the body text neutral against the background neutral for 4.5:1 contrast — if it fails, the most common text pairing in the product is inaccessible.

Documenting as a Design System

The palette is finished when it is documented. A hex code in a Slack message is not documentation; it is a future inconsistency. A design system names every color, assigns it a token, and publishes both so that developers use the token and designers use the name. The documentation should include:

  • Token names. color.primary.500, color.neutral.700, color.semantic.success — names that survive a re-skin, because they describe the role, not the value.
  • Hex values. The exact value for each token, with no rounding.
  • Usage rules. Which token is for backgrounds, which is for text, which is for borders, which is for hover. A token without a usage rule is a token that gets used wrong.
  • Contrast pairs. The tested combinations — primary on white, body text on background, button text on primary — with their ratios and AA/AAA status, so no one re-checks what is already known.
  • Dark mode. A mirrored set of tokens for dark mode, where the lightness ramp inverts and the neutrals shift. Dark mode is not "invert the colors"; it is a separate palette tuned so the same contrast ratios hold against a dark background.

The point of the documentation is that a new designer or developer can build a screen that matches the brand without asking anyone. If they cannot, the system is incomplete.

Summary

Building a brand palette is a sequence, not a selection. Start with brand personality in three adjectives, and let those adjectives narrow the hue space. Pick one primary color that passes contrast for both text and button use. Generate a 50–900 lightness ramp from that primary, holding hue constant and shifting lightness with gentle saturation reduction at the extremes. Add a secondary and an accent for jobs the primary cannot do, plus semantic colors for success, warning, error, and info — kept separate from the brand palette so function never blurs into branding. Build a tinted neutral ramp for backgrounds, borders, and text, and check its body-text pairing for 4.5:1. Document every color as a named token with a hex value, a usage rule, and a tested contrast pair, including a mirrored dark-mode set. The result is not a palette but a system — one that scales across teams, surfaces, and themes without drifting apart.

References & Resources