RGB to HEX Converter

Type the three values from 0 to 255, or paste an rgb() from your CSS, and see the HEX code as you type. With transparency, you get 8-digit HEX.

  • HEX#5271FF
  • hsl()hsl(229 100% 66%)

Need it the other way around? HEX to RGB

Want to know if your RGB has a CSS name? Check the HTML color table with the 148 names and their values.

See the table

How to convert RGB to HEX

Converting RGB to HEX means turning each channel from decimal into hexadecimal and joining the three pairs after a #. By hand, divide the channel by 16: the quotient is the first digit and the remainder is the second.

82  = 5 × 16 + 2    →  5, 2   →  52
113 = 7 × 16 + 1    →  7, 1   →  71
255 = 15 × 16 + 15  →  F, F   →  FF
rgb(82 113 255)  →  #5271FF

A quotient or remainder from 10 to 15 becomes a letter: 10 is A, 11 is B, 12 is C, 13 is D, 14 is E and 15 is F. A second example, with a zero channel:

255 = 15 × 16 + 15  →  FF
128 = 8 × 16 + 0    →  80
0   = 0 × 16 + 0    →  00
rgb(255 128 0)  →  #FF8000

A zero channel still takes two digits (00). HEX with transparency, the 8-digit kind, has its own section below. And when both digits of every pair match, you can shorten the code: rgb(255 0 0) becomes #F00. The tool shows the short HEX whenever one exists.

The leading zero

The classic bug when building HEX by hand is toString(16). It does not pad with a zero: channel 15 becomes f, not 0f. With a channel like that the code loses a digit and turns into a different color, without any error:

(15).toString(16);                  // "f"
(15).toString(16).padStart(2, "0");  // "0f"

"#" + [15, 0, 0].map((c) => c.toString(16)).join("");
// "#f00"  (and not "#0f0000")

Notice that #f00 is valid short HEX, equal to #ff0000. The browser accepts it, but the color is wrong. The fix is padStart(2, '0'), which pads with a leading zero until there are two digits.

Transparency in HEX

For transparency, multiply the alpha (from 0 to 1) by 255, round it and convert the result to hexadecimal. The pair goes at the end of the code and makes the 8-digit HEX. In the field, alpha can be 0.5, .5 or 50%: all three give the same result.

alpha = 0.5
0.5 × 255 = 127.5  →  128
128 = 8 × 16 + 0   →  80
rgb(82 113 255 / 50%)  →  #5271FF80

Why does 50% give 80 and not 7F? Because 0.5 × 255 is 127.5, and rounding goes up to 128 (80). Truncating instead of rounding lands on 127 (7F). The difference is 1 in 255, invisible on screen, but it shows up if you compare two tools byte by byte.

Going back, 8-digit HEX turns into alpha by dividing the last pair by 255 (80 gives 0.5). The HEX to RGB converter does that math and shows the ready-made rgba().

Opacity to HEX table

The pairs to put at the end of the code, from 100% to 0%, in steps of 5. The third column shows the result on top of #5271FF.

Opacity percentage and the matching HEX pair
OpacityHEX pairExample
100% FF #5271FFFF
95% F2 #5271FFF2
90% E6 #5271FFE6
85% D9 #5271FFD9
80% CC #5271FFCC
75% BF #5271FFBF
70% B3 #5271FFB3
65% A6 #5271FFA6
60% 99 #5271FF99
55% 8C #5271FF8C
50% 80 #5271FF80
45% 73 #5271FF73
40% 66 #5271FF66
35% 59 #5271FF59
30% 4D #5271FF4D
25% 40 #5271FF40
20% 33 #5271FF33
15% 26 #5271FF26
10% 1A #5271FF1A
5% 0D #5271FF0D
0% 00 #5271FF00

To use one, append the pair to the six-digit HEX: 40% opacity on #5271FF is #5271FF66. That works in background, color, border-color, box-shadow and even in the stops of a linear-gradient.

Convert RGB to HEX in code

In JavaScript, combine toString(16) with padStart(2, '0') so you do not lose the leading zero:

const toHex = (value) =>
  Math.round(value).toString(16).padStart(2, "0");

function rgbToHex(r, g, b, a) {
  const alpha = a === undefined ? "" : toHex(a * 255);

  return `#${toHex(r)}${toHex(g)}${toHex(b)}${alpha}`.toUpperCase();
}

rgbToHex(82, 113, 255);       // "#5271FF"
rgbToHex(82, 113, 255, 0.5);  // "#5271FF80"
rgbToHex(15, 0, 0);           // "#0F0000"

In Python, the f-string with :02X already pads with zeros and uppercases. hex(255) returns '0xff', with a prefix and no leading zero, so the f-string is usually handier:

def rgb_to_hex(r: int, g: int, b: int) -> str:
    if not all(0 <= channel <= 255 for channel in (r, g, b)):
        raise ValueError("channel out of range 0-255")

    return f"#{r:02X}{g:02X}{b:02X}"

rgb_to_hex(82, 113, 255)  # '#5271FF'
rgb_to_hex(15, 0, 0)      # '#0F0000'

The trap is not validating the 0 to 255 range. Without that check, channel 300 becomes 12c, which has three digits, and the whole code comes out misaligned:

(300).toString(16);   // "12c"
(-1).toString(16);    // "-1"

If the value comes from a text field, convert it with Number() and check it with Number.isInteger. The string "82" works, but "8 2" becomes NaN.

What CSS accepts in rgb()

The tool reads the same formats as the CSS rgb(), so you can paste straight from your stylesheet:

  • Percentages: rgb(100% 0% 0%) is the same as rgb(255 0 0).
  • Decimals: rgb(82.4 113 255) is valid CSS. Here the channel is rounded to the nearest integer.
  • Values outside 0-255: CSS does not error, it clamps to the maximum or minimum, so rgb(300 0 0) becomes rgb(255 0 0). The tool warns you instead, because it is almost always a typo.
  • Separators: 82,113,255 and 82 113 255 both work, and a loose fourth number is read as transparency from 0 to 1.

The space and slash syntax for transparency, and how it differs from rgba() with commas, is explained in the HEX to RGB converter.

More color tools

For the opposite direction, use the HEX to RGB converter. If you need a test image with background and text colors in HEX, the dummy image generator accepts the codes you just converted.