CSS Gradients and Design Systems: Building Visual Consistency
CSS gradient types and syntax, repeating gradients, what design systems and tokens are, and how to build a color scale from HSL.
Every color you see on a screen is built from the same three ingredients: red, green, and blue light. Yet designers and developers refer to colors in at least three different notations — #FF3366, rgb(255, 51, 102), and hsl(345, 100%, 60%). They all describe the exact same pink. So why do we need three formats, and when should you reach for each one?
Screens work by additive color mixing. Each pixel contains a tiny red, green, and blue sub-pixel. When all three fire at full power, you see white. When none fire, you see black. Everything in between is a blend of those three channels at different intensities.
This is the opposite of how paint works. Mix red, yellow, and blue paint and you get a muddy brown — that's subtractive mixing, where pigments absorb light. Screens emit light, so more color means brighter, not darker.
RGB stands for Red, Green, Blue. Each channel is a number from 0 to 255, representing how much of that color to emit. Zero means off, 255 means full blast.
rgb(255, 0, 0) → pure red
rgb(0, 255, 0) → pure green
rgb(0, 0, 255) → pure blue
rgb(255, 255, 0) → yellow (red + green)
rgb(0, 0, 0) → black (nothing on)
rgb(255, 255, 255) → white (everything on)Each channel gets 8 bits of data (one byte). 28 = 256 possible values, giving us the 0–255 range. Three channels means 24 bits total, which produces 16.7 million possible colors — more than enough to look continuous to the human eye.
RGB is what the hardware understands. Your GPU, your monitor, your camera sensor — they all speak RGB. When you write rgb(255, 51, 102) in CSS, you're essentially giving the pixel direct instructions.
HEX color codes are not a different color system — they're just RGB written in base 16 (hexadecimal) instead of base 10. The six characters after the # are three pairs, each representing one RGB channel.
#FF3366
││││││
││││└┘ Blue: 66 hex = 102 decimal
││└┘ Green: 33 hex = 51 decimal
└┘ Red: FF hex = 255 decimal
So #FF3366 = rgb(255, 51, 102)Hex is more compact. #FF3366 is shorter than rgb(255, 51, 102). In the early web, every byte mattered — HTML files were hand-typed over dial-up connections. HEX became the standard for CSS colors simply because it was terse and unambiguous.
When both digits in each pair are the same, you can shorten to three characters. #FF3366 becomes #F36. The browser expands each digit by doubling it: F→FF, 3→33, 6→66.
#FF3366 is universally understoodRGB and HEX are great for machines, but terrible for humans. Quick: is rgb(51, 102, 255) a warm or cool color? Hard to tell at a glance. That's where HSL comes in.
HSL stands for Hue, Saturation, Lightness. It describes color the way people actually think about it:
hsl(345, 100%, 60%) → vivid pink
hsl(345, 100%, 80%) → lighter pink (same hue, more light)
hsl(345, 30%, 60%) → muted pink (same hue, less saturation)
hsl(200, 100%, 60%) → vivid blue (different hue, same formula)calc()Here's how the same set of colors looks in all three formats:
| Color | HEX | RGB | HSL |
|---|---|---|---|
#FF3366 | #FF3366 | 255, 51, 102 | 345, 100%, 60% |
#FFD600 | #FFD600 | 255, 214, 0 | 50, 100%, 50% |
#0055FF | #0055FF | 0, 85, 255 | 220, 100%, 50% |
#00CC66 | #00CC66 | 0, 204, 102 | 150, 100%, 40% |
#1A1A1A | #1A1A1A | 26, 26, 26 | 0, 0%, 10% |
There is no single “best” format. Each one fits a different context:
The good news is that converting between them is instant and lossless. They all describe the same 16.7 million colors — just from different angles. Think of HEX and RGB as the same language with different alphabets, and HSL as a completely different language that maps perfectly to the others.
Knowing all three formats doesn't mean you use all three everywhere. It means you pick the right one for the job — and switch effortlessly when the context changes.
CSS gradient types and syntax, repeating gradients, what design systems and tokens are, and how to build a color scale from HSL.
Lossy vs lossless compression, when transparency matters, and why WebP is replacing both PNG and JPG on the web.
What happens when you drag the quality slider, how DCT transforms photos, and why screenshots compress differently.