HWB Color: Hue, Whiteness and Blackness
hwb() picks a hue, then adds whiteness and blackness as percentages: hwb(199 20% 10%). It mirrors how a painter tints a colour with white or shades it with black. Whiteness plus blackness at 100% yields grey.
Why it matters
HWB is the format that thinks like mixing paint. Start with a fully saturated hue, then mix in white to lighten (a tint) or black to darken (a shade). It is lovely for building tint-and-shade ramps.
The catch: HWB never really caught on the way HSL did, so you will see it far less in the wild. Reach for it when the mental model fits; otherwise hsl() and oklch() cover the same ground with more support and more tooling.
How it works
The mechanism is straightforward. Start from the fully saturated hue, then mix in W whiteness and B blackness, both as percentages.
hwb(199 0% 0%)is the pure blue at hue 199.hwb(199 50% 0%)mixes in 50% white, giving a pastel blue.hwb(199 0% 50%)mixes in 50% black, giving a dark navy.hwb(199 25% 25%)mixes both, landing somewhere in between.
When whiteness plus blackness reaches 100% or more, the colour collapses to grey. hwb(199 60% 50%) adds up to 110%, so the result is a neutral grey, ignoring the hue.
Syntax is straightforward: hwb(hue whiteness blackness), with an optional slash for alpha: hwb(199 20% 10% / 0.5).
What does not matter
HWB lightness is not perceptual either. Like HSL, hwb(60 50% 0%) (a tinted yellow) and hwb(240 50% 0%) (a tinted blue) can look different in brightness even though both have the same whiteness. If you need perceptually even palettes, upgrade to oklch().
The choice between HWB and HSL is about mental models, not output quality. Both can produce the same colours; pick whichever one you think about more easily.
Code example
/* Tinting by mixing white */
:root {
--base-hue: 199;
--dark-navy: hwb(var(--base-hue) 0% 60%); /* Shade: lots of black */
--standard-blue: hwb(var(--base-hue) 0% 0%); /* The pure hue */
--pastel-blue: hwb(var(--base-hue) 60% 0%); /* Tint: lots of white */
}
/* Building a shade ramp by walking blackness up */
.shade-1 { background: hwb(199 0% 10%); } /* Slightly dark */
.shade-2 { background: hwb(199 0% 30%); } /* Darker */
.shade-3 { background: hwb(199 0% 60%); } /* Very dark */
/* Wrong: oversaturated on a weak monitor */
.error {
color: hwb(0 0% 0%); /* Pure red. Readable, but harsh. */
}
How Scalpel Color shows it
Open the Picker tab. The HWB row shows the current colour's hue, whiteness and blackness. You can adjust all three using sliders. When you mix white and black to 100% or more, the extension shows the result greying out.