How to Build a Color Palette (and Convert Between HEX, RGB, and HSL)

Color is the design decision people make fastest and regret longest. A palette chosen in five minutes ends up in a logo, a website, a slide deck, and a business card — and changing it later means changing all of them.

The good news is that a working palette is not a matter of taste. It is a matter of a few constraints, and they are easy to check.

Extracting colors from an image

The fastest way to start is to pull the colors out of something that already looks right — a photo, a product shot, a piece of art. The palette generator does this by clustering pixels by similarity (a technique called median-cut quantization) and returning the colors that genuinely dominate.

Two things it will not do for you.

Dominant is not the same as good. The colors that dominate a photograph are usually the background, the sky, or skin tones — not the colors you would want as brand accents. A beach photo hands you sand, sky, and sea, all of them low-saturation and nearly the same lightness. That is an accurate extraction and a poor palette.

Extraction has no idea what the colors are for. A palette needs a dark, a light, and something in between, because text, backgrounds, and accents have different jobs. What you get from an image is a set of colors, not a system.

The fix for both is the same: extract, then choose. Crop the image down to the region whose colors you actually want before extracting — cropping a product photo to just the product removes the background from the result entirely.

HEX, RGB, HSL — and which one to think in

All three describe the same colors. They differ in how easy they are to reason about.

HEX (#3B82F6) is the most compact and the most common in CSS. It is a hex encoding of the three RGB channels. Excellent for shipping, terrible for thinking — you cannot look at #3B82F6 and tell what it would look like a bit lighter.

RGB (rgb(59, 130, 246)) is the same information written as three numbers. More readable, and it is what you need when you add transparency: rgba(59, 130, 246, 0.5).

HSL (hsl(217, 91%, 60%)) describes the color the way a person does: hue, saturation, lightness. This is the one worth thinking in, for one reason — adjusting a color means changing one number instead of three. To lighten a blue in HSL, raise the third value. To mute it, lower the second. Try the same in HEX and you are guessing.

The workflow most design systems use: define in HSL, ship in HEX. Keep the HSL values as your source of truth so you can generate consistent shades later, and convert to HEX for the CSS. The color converter moves between all three instantly, which is what makes this practical rather than pedantic.

Building shades that actually match

Once you have a base color, you need a range — a light tint for backgrounds, a dark shade for text, something for hover states.

The mistake is to change lightness alone. A color lightened 20% at full saturation goes pastel and neon at the same time. Two adjustments keep a ramp coherent:

Reduce saturation as you lighten. Tints look natural when they lose some chroma on the way up. 90% lightness at 100% saturation is a warning color; at 40% saturation it is a usable background.

Reduce saturation as you darken, too. Very dark colors at high saturation read as muddy. Deep shades usually want saturation in the 40–60% range.

A working ramp for one brand color is typically five to nine stops, from near-white to near-black, all sharing a hue. That is enough for backgrounds, borders, text, and states without inventing a second color family.

The check nobody runs: contrast

A palette can look beautiful and fail the one test that matters for readability.

The Web Content Accessibility Guidelines set the bar: 4.5:1 contrast ratio for body text, 3:1 for large text and for the boundaries of interactive controls. These are not aesthetic preferences — they are the point at which text stops being reliably readable for people with reduced vision, on a bad screen, or in sunlight.

The trap is that the failures are invisible to the person choosing the colors. Grey text on a white background at 4:1 looks perfectly fine on a calibrated monitor and disappears on a phone at 30% brightness.

Two habits prevent it:

Never pick text and background colors independently. Check them as a pair, at the ratio, before committing.

Remember that contrast is about luminance, not hue. Two colors can look very different and have almost identical brightness — a saturated blue and a saturated red are the classic example. Converting both to HSL and comparing the L values is a fast sanity check: if the two L numbers are close, the contrast is poor regardless of how different the colors appear.

Frequently asked questions

How many colors should a palette have? One primary, one or two accents, plus a neutral ramp of five to nine stops. More than that and consistency becomes impossible to maintain across a team.

Should I use HEX or RGB in CSS? HEX for opaque colors, rgb() / rgba() when you need transparency. HSL works in modern CSS too, and it is the best format to store your source values in.

Why does my extracted palette look dull? Because dominant colors in photographs are usually backgrounds — low saturation, similar lightness. Crop to the subject before extracting, or treat the extraction as a starting point and raise the saturation.

What contrast ratio do I need? 4.5:1 for normal text, 3:1 for large text (roughly 18pt, or 14pt bold) and for UI component boundaries. Higher is better for anything that must stay readable in poor conditions.

Can I use one color for the whole design? Yes, and single-hue palettes are often the most coherent. You need enough lightness range to separate text from background — usually five stops or more.

How do I make a color lighter without washing it out? Raise lightness and lower saturation at the same time. Lightening at full saturation is what produces that pastel-and-neon look.

Tools mentioned in this guide

← All guides