Color picking is not just selecting a hex string. A picker exposes a representation of a color; the displayed result also depends on the source profile, transfer function, alpha compositing, display, and user settings. This guide separates notation from appearance and shows how to build a palette that can be tested in a real interface.
Table of Contents
- Key Takeaways
- Color Models Explained
- Web Color Formats
- Color Format Conversion
- Code Examples
- Best Practices
- Frequently Asked Questions
- Conclusion
Key Takeaways
- RGB is Additive: Red, green, blue light combine to produce colors, used for screen display
- HSL is an authoring control: Hue, saturation, and lightness can be convenient, but HSL is not perceptually uniform
- HEX is RGB Shorthand: Hexadecimal format is a compact representation of RGB values
- Transparency Support: RGBA and HSLA support alpha channel for semi-transparent effects
- CSS Variables: Use CSS custom properties to manage colors for easy theme switching
Color Models Explained
RGB Model
RGB (Red, Green, Blue) is an additive color model that produces colors by combining different intensities of red, green, and blue light.
Characteristics:
- Each channel value range: 0-255
- Total colors: 256³ = 16,777,216
- Used for screen display (light-emitting devices)
Color Mixing Examples:
| Color | R | G | B |
|---|---|---|---|
| Red | 255 | 0 | 0 |
| Green | 0 | 255 | 0 |
| Blue | 0 | 0 | 255 |
| Yellow | 255 | 255 | 0 |
| Cyan | 0 | 255 | 255 |
| Magenta | 255 | 0 | 255 |
| White | 255 | 255 | 255 |
| Black | 0 | 0 | 0 |
HSL Model
HSL (Hue, Saturation, Lightness) is a convenient cylindrical representation for authoring, not a perceptual scale. Equal changes in L do not produce equal perceived lightness across hues.
Parameters:
- Hue: 0-360 degrees, position on the color wheel
- 0°/360°: Red
- 120°: Green
- 240°: Blue
- Saturation: 0%-100%, color vividness
- 0%: Gray
- 100%: Pure color
- Lightness: 0%-100%, brightness level
- 0%: Black
- 50%: Pure color
- 100%: White
HSV/HSB Model
HSV (Hue, Saturation, Value), also called HSB (Brightness), is similar to HSL but with different brightness definition.
Web Color Formats
HEX Format
In CSS, hexadecimal notation represents sRGB channels. It may contain 3, 4, 6, or 8 hex digits; the 4/8-digit forms include alpha.
/* 6-digit format */
color: #FF5733;
color: #ffffff;
/* 3-digit shorthand */
color: #F53; /* equals #FF5533 */
color: #fff; /* equals #ffffff */
/* 8-digit format (with alpha) */
color: #FF573380; /* last two digits are alpha */
RGB/RGBA Format
/* RGB format */
color: rgb(255, 87, 51);
/* RGBA format (with alpha) */
color: rgba(255, 87, 51, 0.5);
/* Modern CSS syntax */
color: rgb(255 87 51);
color: rgb(255 87 51 / 50%);
HSL/HSLA Format
/* HSL format */
color: hsl(11, 100%, 60%);
/* HSLA format (with alpha) */
color: hsla(11, 100%, 60%, 0.5);
/* Modern CSS syntax */
color: hsl(11 100% 60% / 50%);
Color Keywords
CSS defines a finite set of named color keywords:
color: red;
color: blue;
color: transparent;
color: currentColor;
Color Format Conversion
HEX to RGB
function hexToRgb(hex) {
const value = String(hex).replace(/^#/, '');
const expanded = value.length === 3 || value.length === 4
? [...value].map(char => char + char).join('')
: value;
if (!/^[\da-f]{6}([\da-f]{2})?$/i.test(expanded)) {
throw new RangeError('expected #RGB, #RGBA, #RRGGBB, or #RRGGBBAA');
}
return {
r: parseInt(expanded.slice(0, 2), 16),
g: parseInt(expanded.slice(2, 4), 16),
b: parseInt(expanded.slice(4, 6), 16),
...(expanded.length === 8
? { a: parseInt(expanded.slice(6, 8), 16) / 255 }
: { a: 1 })
};
}
hexToRgb('#FF5733'); // { r: 255, g: 87, b: 51 }
RGB to HEX
function rgbToHex(r, g, b) {
const channels = [r, g, b];
if (!channels.every(Number.isInteger) ||
channels.some(channel => channel < 0 || channel > 255)) {
throw new RangeError('RGB channels must be integers from 0 to 255');
}
return '#' + [r, g, b].map(x => {
const hex = x.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}).join('');
}
rgbToHex(255, 87, 51); // '#ff5733'
Code Examples
CSS Variables for Color Management
:root {
--color-primary: #3498db;
--color-primary-light: #5dade2;
--color-primary-dark: #2980b9;
--color-success: #27ae60;
--color-warning: #f39c12;
--color-error: #e74c3c;
}
.button-primary {
background-color: var(--color-primary);
}
/* Dark theme */
[data-theme="dark"] {
--color-text: #ffffff;
--color-background: #1a1a1a;
}
JavaScript Color Class
class Color {
constructor(r, g, b, a = 1) {
this.r = r;
this.g = g;
this.b = b;
this.a = a;
}
static fromHex(hex) {
const value = hexToRgb(hex);
return new Color(value.r, value.g, value.b, value.a);
}
toHex() {
const toHex = n => n.toString(16).padStart(2, '0');
return `#${toHex(this.r)}${toHex(this.g)}${toHex(this.b)}`;
}
lighten(percent) {
if (!Number.isFinite(percent) || percent < 0 || percent > 100) {
throw new RangeError('percent must be between 0 and 100');
}
// Channel arithmetic is illustrative; use a perceptual space for production palettes.
const amount = Math.round(255 * percent / 100);
return new Color(
Math.min(255, this.r + amount),
Math.min(255, this.g + amount),
Math.min(255, this.b + amount)
);
}
}
Best Practices
1. Use Semantic Color Names
/* Recommended */
--color-primary: #3498db;
--color-success: #27ae60;
/* Not recommended */
--blue: #3498db;
--green: #27ae60;
2. Build a Color System
--color-primary-50: #e3f2fd;
--color-primary-100: #bbdefb;
--color-primary-500: #2196f3; /* Base color */
--color-primary-900: #0d47a1;
3. Ensure Contrast Ratio
For WCAG 2.x AA, normal text generally needs at least 4.5:1 and large text 3:1. Large text is defined by rendered point size and weight, not a universal CSS pixel value. Test focus indicators, non-text graphics, disabled states, and alpha-composited colors too.
4. Support Dark Mode
@media (prefers-color-scheme: dark) {
:root {
--color-text: #ffffff;
--color-background: #121212;
}
}
Frequently Asked Questions
What's the difference between HEX and RGB?
HEX is a hexadecimal notation for RGB channel values, not a new color model. HEX is compact, while RGB makes channels and alpha more explicit.
When should I use HSL?
When you need to adjust color brightness or saturation, HSL is more convenient. For example, creating different shades of the same hue.
How do I choose appropriate color contrast?
Use the intended sRGB foreground and the actual composited background, then verify the rendered component. WCAG ratios do not replace testing focus visibility, state changes, images, gradients, or user-selected themes.
Does a color picker show the “true” color?
Not necessarily. Appearance depends on color profiles, display gamut, brightness, ambient light, browser behavior, and alpha compositing. Preserve profile metadata for images and treat a picker value as a representation with stated assumptions.
Conclusion
Understanding models and web color formats helps teams create maintainable palettes, but a hex value alone does not guarantee appearance or accessibility. Use semantic tokens, test real states, and document the color space and contrast assumptions.
Quick Summary:
- RGB for screen-oriented channel values; HSL is a convenient authoring representation, not a perceptual guarantee
- HEX is compact RGB representation, most common in web development
- Use CSS variables to manage colors for easy theme switching
- Ensure text and background contrast meets accessibility standards
- Build systematic color schemes with primary, secondary, and semantic colors