Medium

HEX to RGB

Prompt

Write a JavaScript function that takes a string representing a color in hexadecimal format and returns an object representing the equivalent color in RGB (Red, Green, Blue) format.

  • The input will be a string starting with # followed by either 3 or 6 hexadecimal characters (e.g. #fff or #0080ff).
  • For 3-character shorthand, each character should be doubled (e.g. #abc becomes #aabbcc).
  • The resulting object should have keys r, g, and b, each holding a decimal number between 0 and 255.
  • Do not use regular expressions or external libraries.

Playground

Hint 1

Hex colors can come in shorthand form, like #abc, which is equivalent to #aabbcc. Start by normalizing the input so you always work with a 6-character string.

Hint 2

Each pair of characters in a 6-character hex color represents one color component (red, green, blue). Use slice or substring to extract each pair.

Hint 3

Use parseInt with a radix of 16 to convert each two-character hex string into its decimal equivalent. For example, parseInt('ff', 16) returns 255.

Solution

Explanation

Hex-to-RGB conversion comes up surprisingly often in interviews, and it's a great question because it touches on string manipulation, number systems, and attention to edge cases.

A hexadecimal color code is really just three two-digit base-16 numbers concatenated together, each representing the intensity of red, green, and blue on a 0 to 255 scale. The # at the front is just a convention to signal "this is a hex color."

The first thing the function does is strip that leading # using startsWith and slice. Then it handles the shorthand notation. A 3-character hex code like #abc is just a compressed form of #aabbcc, where each digit gets doubled. The function expands it by repeating each character: color[0] + color[0] + color[1] + color[1] + color[2] + color[2].

After normalization, we validate that we have exactly 6 characters. If not, something is wrong with the input, and we throw an error.

The actual conversion uses parseInt with a radix of 16. When you call parseInt('ff', 16), JavaScript reads ff as a base-16 number and returns its decimal equivalent, 255. Each pair of hex digits maps to one color channel: the first two for red, the next two for green, the last two for blue.

To understand why this works mathematically, consider a two-digit hex number XY. In base-16, the left digit is in the "sixteens" place and the right digit is in the "ones" place, so the decimal value is X * 16 + Y. For FF, that's 15 * 16 + 15 = 255, which is the maximum value for a single color channel. For a full color like #3BCDEF, you'd calculate each pair separately: 3B is 3 * 16 + 11 = 59, CD is 12 * 16 + 13 = 205, and EF is 14 * 16 + 15 = 239, giving rgb(59, 205, 239).

The shorthand expansion is the part candidates forget most often. If you don't handle #FFF as a valid input, you'll lose points even if the rest of your logic is perfect.