Understanding HEX, RGB, and HSL: Color Models Explained for Developers and Designers
HEX, RGB, and HSL are three ways to describe the same colors. This guide explains how each model works, the math behind conversions, and when to use which in CSS, design tools, and code.
Every color you see on a screen is described by numbers. The question is which numbers and which system. The same shade of blue can be written as #3B82F6 in HEX, rgb(59, 130, 246) in RGB, or hsl(217, 91%, 60%) in HSL — three different notations that all produce the exact same color. Understanding these three color models — how they work, how they relate to each other, and when to use each one — is essential for anyone writing CSS, working in design tools, or building interfaces.
This guide explains each model from the ground up, covers the math behind conversions, and provides practical guidance on which model to use in different contexts.
RGB: How Screens Actually Make Color
RGB (Red, Green, Blue) is the foundational color model for all screen-based color. It's an additive model — colors are created by adding light. A pixel on your screen is made of three tiny sub-pixels: one red, one green, and one blue. By varying the intensity of each sub-pixel from 0 (off) to 255 (full brightness), the display can produce approximately 16.7 million colors (256 x 256 x 256 = 16,777,216).
rgb(255, 0, 0) is pure red — the red sub-pixel is at full brightness, green and blue are off. rgb(0, 255, 0) is pure green. rgb(0, 0, 255) is pure blue. rgb(255, 255, 255) is white — all three at full brightness. rgb(0, 0, 0) is black — all three off. rgb(128, 128, 128) is a medium gray — all three at equal, half brightness.
The additive nature of RGB is counterintuitive if you're used to mixing paint (which is subtractive — mixing all colors gives you a muddy brown or black). In RGB, mixing red and green light gives you yellow (rgb(255, 255, 0)), mixing red and blue gives you magenta (rgb(255, 0, 255)), and mixing green and blue gives you cyan (rgb(0, 255, 255)). This is why RGB is sometimes called the "light mixing" model.
In CSS, RGB colors are written as rgb(red, green, blue) where each value is an integer from 0 to 255. Modern CSS also supports the syntax rgb(red green blue) (space-separated, no commas) and percentage values like rgb(23% 51% 96%). The rgba() function adds an alpha (transparency) channel: rgba(59, 130, 246, 0.5) is that same blue at 50% opacity. In CSS Color Level 4, the alpha can be included in the rgb() function itself using a slash: rgb(59 130 246 / 0.5).
RGB is the "machine" color model — it maps directly to how display hardware works. Every other color model used in web development is ultimately converted to RGB values before the screen can display them.
HEX: RGB in Compact Notation
HEX (hexadecimal) color codes aren't a different color model — they're a different notation for RGB values. The hex code #3B82F6 is exactly rgb(59, 130, 246) written in base-16 instead of base-10.
A six-digit hex code is three pairs of hexadecimal digits: the first pair is the red channel, the second pair is the green channel, and the third pair is the blue channel. Each pair represents a value from 00 (0 in decimal) to FF (255 in decimal). So #3B82F6 breaks down as: 3B (red = 59), 82 (green = 130), F6 (blue = 246).
Hexadecimal uses the digits 0-9 plus the letters A-F to represent values 0-15 in a single character. Each hex digit represents 4 bits, so two hex digits represent 8 bits (one byte) — exactly the range needed for a color channel value of 0-255. This compactness is why hex became the dominant color notation in web development: #3B82F6 is shorter than rgb(59, 130, 246).
CSS also supports three-digit hex shorthand: #F00 is equivalent to #FF0000 (red), #0F0 to #00FF00 (green), and #FFF to #FFFFFF (white). Each digit is doubled: #ABC becomes #AABBCC. This only works when each pair consists of two identical digits.
Eight-digit hex codes add an alpha channel: #3B82F680 is rgb(59, 130, 246) at 50% opacity (80 in hex is 128 in decimal, which is approximately 50% of 255). Four-digit shorthand works the same way: #F008 is red at approximately 53% opacity.
Our hex color converter converts between hex and other formats. The RGB to HEX converter and HEX to RGB converter handle the specific conversion between these two notations.
HSL: Color as Humans Think About It
HSL (Hue, Saturation, Lightness) describes color the way humans intuitively think about it — by its hue (what color is it?), its saturation (how vivid is it?), and its lightness (how bright or dark is it?).
Hue is the color's position on the color wheel, expressed as an angle from 0 to 360 degrees. 0 (and 360) is red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, and 300 is magenta. The entire visible spectrum is arranged in a circle, which is why hue wraps around — 0 and 360 are the same color.
Saturation is the color's intensity or vividness, from 0% (completely desaturated — a shade of gray) to 100% (fully saturated — the most vivid version of that hue). Reducing saturation moves the color toward gray; a color at 0% saturation is pure gray regardless of its hue.
Lightness is the color's brightness, from 0% (black) to 100% (white), with 50% being the "normal" full-color version. At 0% lightness, every color is black. At 100% lightness, every color is white. At 50% lightness, you get the pure, fully saturated hue. This is different from "brightness" or "value" in the related HSB/HSV model, where 100% value with full saturation gives you the pure hue (not white).
In CSS, HSL colors are written as hsl(hue, saturation%, lightness%) — for example, hsl(217, 91%, 60%) for our reference blue. The hsla() function adds alpha: hsla(217, 91%, 60%, 0.5). Modern CSS also supports hsl(217 91% 60% / 0.5).
HSL's power is in its intuitiveness. Want a darker version of a color? Decrease the lightness. Want a more muted version? Decrease the saturation. Want a complementary color? Add 180 to the hue. Want an analogous color palette? Add or subtract 30 from the hue. These operations are trivial in HSL but require complex calculations in RGB or HEX.
The Math: Converting Between Models
Converting between HEX and RGB is straightforward — it's just a base conversion.
HEX to RGB: Split the hex string into three pairs, convert each pair from base-16 to base-10. The hex value 3B converts to 3 x 16 + 11 = 59. The hex value 82 converts to 8 x 16 + 2 = 130. The hex value F6 converts to 15 x 16 + 6 = 246. Result: rgb(59, 130, 246).
RGB to HEX: Convert each decimal value to base-16 and concatenate. 59 in decimal is 3B in hex. 130 is 82. 246 is F6. Result: #3B82F6.
Converting between RGB and HSL involves more complex math. The algorithm for RGB to HSL is as follows. First, normalize the RGB values to the 0-1 range by dividing by 255. Find the maximum and minimum of the three normalized values. Lightness is the average of the max and min: L = (max + min) / 2. If max equals min, the color is a shade of gray (saturation is 0 and hue is undefined). Otherwise, saturation depends on lightness: if L is less than or equal to 0.5, then S = (max - min) / (max + min); if L is greater than 0.5, then S = (max - min) / (2 - max - min). Hue is calculated from which RGB channel is the maximum: if red is max, H = (G - B) / (max - min); if green is max, H = 2 + (B - R) / (max - min); if blue is max, H = 4 + (R - G) / (max - min). Multiply by 60 to get degrees, and add 360 if negative.
The reverse (HSL to RGB) is equally formulaic. If saturation is 0, all RGB values equal the lightness (it's a gray). Otherwise, calculate temporary values based on lightness and saturation, then compute each RGB channel based on the hue using a helper function that handles the wrapping of the hue angle.
You don't need to memorize these formulas — our hex color converter and related tools handle all conversions automatically. But understanding that the conversion exists and is lossless (every RGB color has exactly one HSL representation and vice versa) helps you choose the right model for each task.
HSV/HSB: The Design Tool Model
You'll also encounter HSV (Hue, Saturation, Value) or HSB (Hue, Saturation, Brightness) — the same model under two names. This is the color model used by most design tool color pickers, including those in Photoshop, Figma, Sketch, and Illustrator.
HSV shares the same hue wheel as HSL. The difference is in the second and third components. In HSV, "value" (or "brightness") at 100% gives you the fully saturated hue, while in HSL, "lightness" at 100% gives you white. The visual difference: HSV's color picker is a square where the top edge shows fully bright colors fading from saturated (left) to white (right), and the bottom edge is black. HSL's conceptual space is a double cone where the middle band shows fully saturated colors and both the top and bottom taper to white and black.
For CSS, HSL is the standard — CSS doesn't have an hsv() or hsb() function. If you pick a color in a design tool that shows HSB values, you'll need to convert to HSL (or RGB/HEX) for CSS. Most design tools show multiple formats simultaneously, so this isn't usually a problem.
When to Use Which Model
Use HEX when you need a compact, copy-pasteable color value for CSS, design specifications, or code. HEX is the most widely used notation in web development and is supported everywhere. Most design systems (like Tailwind CSS) define their color palettes in HEX.
Use RGB when you need to manipulate individual color channels programmatically, when you're working with graphics APIs (Canvas, WebGL, image processing), or when you need alpha transparency in older CSS that doesn't support eight-digit hex. RGB maps directly to how displays work, making it the natural choice for pixel-level operations.
Use HSL when you need to create color variations programmatically — lighter/darker shades, more/less saturated versions, complementary or analogous colors. HSL's components map to intuitive color properties, making it far easier to create systematic color palettes. In CSS, HSL is increasingly preferred because it's human-readable: hsl(217, 91%, 60%) tells you immediately that it's a highly saturated blue at moderate lightness.
Use HSL for design systems where you need to generate consistent color scales. A common pattern is to define a base hue and saturation, then generate a scale of 10 lightness steps from near-white (lightness 95%) to near-black (lightness 10%). This produces a harmonious color palette with a single hue that works for backgrounds, borders, text, and interactive states. Our color palette generator can help with this.
CSS Color Functions: Modern Options
Modern CSS (Color Level 4 and 5) adds powerful color functions that build on these models.
The color-mix() function blends two colors in a specified color space: color-mix(in srgb, #3B82F6 70%, white) produces a color that's 70% blue and 30% white — a tint. You can mix in different color spaces (srgb, hsl, lab, oklch) for different blending results.
The oklch() function uses the OKLCH color space — a perceptually uniform color model where equal numeric changes produce equal perceived changes. Unlike HSL, where a 10% lightness change looks dramatically different at different hues (yellow HSL lightness behaves very differently from blue HSL lightness), OKLCH provides consistent perceived lightness across hues. It's increasingly recommended for design system color palettes because of this perceptual uniformity.
The color() function provides access to wider color gamuts beyond sRGB — P3 (used by modern Apple and Samsung displays), Rec.2020 (used in HDR video), and others. This enables colors that are more vivid than anything possible in the traditional sRGB gamut that HEX, RGB, and HSL are limited to.
These newer functions don't replace HEX, RGB, and HSL — they extend the color toolbox for specific use cases. For most web development work, the three classic models cover everything you need.
Accessibility and Color
Regardless of which color model you use, accessibility requires sufficient contrast between text and background colors. The Web Content Accessibility Guidelines (WCAG) define minimum contrast ratios: 4.5:1 for normal text and 3:1 for large text at the AA level, and 7:1 for normal text and 4.5:1 for large text at the AAA level.
Contrast ratio is calculated from the relative luminance of the two colors, which is derived from their RGB values using a specific formula that accounts for human perception (the sRGB transfer function). Notably, this calculation uses the linearized RGB values, not the HSL lightness — two colors with the same HSL lightness can have very different perceived luminance (and therefore contrast ratios) because human vision is more sensitive to green light than red or blue.
When choosing colors for text and interactive elements, always verify contrast ratios with a tool rather than relying on visual judgment. Our hex color converter can help you explore color values, and browser DevTools include built-in contrast ratio checking.
The Bottom Line
HEX, RGB, and HSL are three notations for the same 16.7-million-color sRGB space. HEX is compact and universally recognized. RGB maps to display hardware and is natural for pixel-level programming. HSL maps to human color intuition and is ideal for creating variations and palettes. Learn all three, use whichever is most natural for the task at hand, and let conversion tools handle the translation. The color is the same — only the description changes.
References
MDN — CSS Color Values — Complete reference for all CSS color value types including rgb, hsl, hex, oklch, and color-mix.
CSS Tricks — Converting Color Spaces in JavaScript — Detailed walkthrough of RGB-HSL conversion algorithms with code.
Wikipedia — HSL and HSV — Mathematical definitions and comparisons of the HSL and HSV color models.
Niwa.nu — Math Behind Colorspace Conversions — Step-by-step explanation of RGB to HSL conversion formulas.
WCAG — Understanding Contrast — Accessibility guidelines for color contrast ratios.