30

I am using the TweenMax JS library with the ColorPropsPlugin which will tween color values which are specified in many formats, the problem I have is that the result is always in the form of a string:

"rgb(255,255,255)"

How can that be converted in to a hex number like:

0xffffff
2

10 Answers 10

51

I would at first cut away the CSS parts:

var a = "rgb(255,255,255)".split("(")[1].split(")")[0];

Then split it into separate numbers:

a = a.split(",");

Convert the single numbers to hex

var b = a.map(function(x){             //For each array element
    x = parseInt(x).toString(16);      //Convert to a base16 string
    return (x.length==1) ? "0"+x : x;  //Add zero if we get only one character
})

And glue it back together:

b = "0x"+b.join("");
4
  • I'm probably doing something wrong here, but would you check this does work please as I'm getting 0x255255255 - jsfiddle.net/QRk6J/1
    – Neil
    Commented Oct 25, 2012 at 15:18
  • 1
    ok I figured it out, I have to create a new var for the map, eg: var b = a.map etc. I'll edit your answer - jsfiddle.net/QRk6J/2
    – Neil
    Commented Oct 25, 2012 at 15:27
  • Here (Opera), it works with the same var. But good to know, thanks!
    – Nippey
    Commented Oct 25, 2012 at 15:47
  • As a function, var a = str.substring(str.indexOf('(')+1).split(',') works very well because parseInt will ignore the ')' in the last element. No need for a pair of split calls. Commented May 17, 2017 at 20:12
14

The following is adapted from a Colour class I wrote and use but may be overkill for your needs since it handles percentages and negative numbers.

Demo: http://jsfiddle.net/5ryxx/1/

Code:

function componentFromStr(numStr, percent) {
    var num = Math.max(0, parseInt(numStr, 10));
    return percent ?
        Math.floor(255 * Math.min(100, num) / 100) : Math.min(255, num);
}

function rgbToHex(rgb) {
    var rgbRegex = /^rgb\(\s*(-?\d+)(%?)\s*,\s*(-?\d+)(%?)\s*,\s*(-?\d+)(%?)\s*\)$/;
    var result, r, g, b, hex = "";
    if ( (result = rgbRegex.exec(rgb)) ) {
        r = componentFromStr(result[1], result[2]);
        g = componentFromStr(result[3], result[4]);
        b = componentFromStr(result[5], result[6]);

        hex = "0x" + (0x1000000 + (r << 16) + (g << 8) + b).toString(16).slice(1);
    }
    return hex;
}
1
  • I don't need percentages in this case, but as percentages are used in other cases I'll +1 you.
    – Neil
    Commented Oct 25, 2012 at 14:53
6

This is what I did.

String.prototype.toRGB = function() {

  var rgb = this.split( ',' ) ;
  this.r=parseInt( rgb[0].substring(4) ) ; // skip rgb(
  this.g=parseInt( rgb[1] ) ; // this is just g
  this.b=parseInt( rgb[2] ) ; // parseInt scraps trailing )

}

After you run 'rgb(125,181,215)'.toRGB(), you will get .r, .g and .b properties defined (with correct integer values) in the same string object returned.

To get the hex value, simply use yourNumber.toString(16);

0
6

rgb2Hex = s => s.match(/[0-9]+/g).reduce((a, b) => a+(b|256).toString(16).slice(1), '0x')

console.log(rgb2Hex('rgb(10, 11, 12)'), rgb2Hex('rgb(255, 256, 257)'))


Not recommended for unreliable user input, but the string can also be evaluated as a function:

rgb = (r, g, b) => '0x' + (1<<24|r<<16|g<<8|b).toString(16).slice(1)

console.log(eval('rgb(10, 11, 12)'), eval('rgb(255)'))

4
function parseColor(color) {
    var arr=[]; color.replace(/[\d+\.]+/g, function(v) { arr.push(parseFloat(v)); });
    return {
        hex: "#" + arr.slice(0, 3).map(toHex).join(""),
        opacity: arr.length == 4 ? arr[3] : 1
    };
}
function toHex(int) {
    var hex = int.toString(16);
    return hex.length == 1 ? "0" + hex : hex;
}

parseColor("rgb(210, 10, 10)");  // {"hex":"#d20a0a","opacity":1}
parseColor("rgba(210, 10, 10, 0.5)"); // {"hex":"#d20a0a","opacity":"0.5"}
parseColor("rgb(210)");  // {"hex":"#d2","opacity":1}
2
  • It supports both rgb() and rgba().
    – gramcha
    Commented Nov 25, 2017 at 17:25
  • does not handle decimal rgb console.log(JSON.stringify(parseColor("rgb(251.94,247.35,221.85)") ) ); {"hex":"#fb.f0a3d70a3d7f7.599999999998dd.d99999999998","opacity":1}
    – aNewb
    Commented Jul 16, 2021 at 2:43
2
RGBToHex = function(r,g,b){
    var bin = r << 16 | g << 8 | b;
    return (function(h){
        return new Array(7-h.length).join("0")+h
    })(bin.toString(16).toUpperCase())
}

https://gist.github.com/lrvick/2080648

Edited:

cnvrtRGBClrToHex('255,145,20')

function cnvrtRGBClrToHex(rgbClr){
    var rgbClr = rgbClr.split(',');
    var r = rgbClr[0];
    var g = rgbClr[1];
    var b = rgbClr[2];
    return (r << 16 | g << 8 | b).toString(16).toUpperCase()
}
0
2

A codegolfed approach:

var h = x => '#' + x.match(/\d+/g).map(y = z => ((+z < 16)?'0':'') + (+z).toString(16)).join('');

Now, running h("rgb(255, 60, 60)") will return #ff3c3c.

You can replace '#' with '0x' to get outputs in the form of 0xff3c3c.


EXTRA: how it works.

h, declared as an arrow function (new in ES6) takes an RGB value (string) and stores it in x. Then, all instances of numbers in x are found by the regex equation /\d+/g, and used further as an array (returned by match, used by map).

map loops processes all the elements of the returned array by a function y. The function takes a value (which was stored in the array as a string) as z converts it to a number (+z), checks if it is less than 16 (((+z < 16)?'0':''), that is, the hex representation has a single digit), and if true, adds a '0' to the element's start.

Then, it converts it to a string of base 16 (hex, by .toString(16)), and returns it to map. So essentially, all the decimal strings in the array are now changed to hex strings.

Finally, the array's elements are joined together (join('')), with no delimiter and '#' is added to the beginning of the string.


Note: If the code is supplied a value greater than 255, the output will be more than 6 hex digits. Like, the output for rgb(256, 0, 0) will be #1000000.

To constraint the value to 255, this would be the code:

var h = x => '#' + x.match(/\d+/g).map(y = z => ((+z < 16)?'0':'') + ((+z > 255)?255:+z).toString(16)).join('');
2

A readable oneliner for rgb string to hex string:

rgb = "rgb(0,128,255)"
hex = '#' + rgb.slice(4,-1).split(',').map(x => (+x).toString(16).padStart(2,0)).join('')

which returns here "#0080ff".

1

Another way to convert from RGB color to HEX in JavaScript

    color = "rgb(51,51,51);";
    color = '#'+color.match(/\d+/g).map(function(x){
        x = parseInt(x).toString(16);
        return (x.length==1) ? "0"+x : x;
    }).join("");
0

I created this code block to convert RGB color to hexadecimal color in TypeScript and JavaScript. Note: It converts to float and non-float values in the RGB color:

TypeScript code:

function parseFloat(value?: string): number {
  if (!value || Number.isNaN(value)) return -1;

  return Number.parseFloat(value);
}

function isRgbNumber(numberColor: number): boolean {
  if (numberColor !== 0 && !numberColor) return false;

  const MIN_NUMBER_COLOR = 0;
  const MAX_NUMBER_COLOR = 255;

  return numberColor >= MIN_NUMBER_COLOR && numberColor <= MAX_NUMBER_COLOR;
}

function rgbToHexadecimal(rgbColor: string): string | null {
  const LENGTH_OF_RGB_COLOR = 3;

  const regexToRemoveCharacters = /[A-Z()\s]/gi;
  const redGreenAndBlueNumbers = rgbColor
    .toLowerCase()
    .replace(regexToRemoveCharacters, '')
    .split(',');

  if (redGreenAndBlueNumbers.length !== LENGTH_OF_RGB_COLOR) return null;

  const [red, green, blue] = redGreenAndBlueNumbers;
  const allColorsExists = !!red && !!green && !!blue;
  if (!allColorsExists) return null;

  const redNumber = parseFloat(red);
  const greenNumber = parseFloat(green);
  const blueNumber = parseFloat(blue);

  if (
    !isRgbNumber(redNumber) ||
    !isRgbNumber(greenNumber) ||
    !isRgbNumber(blueNumber)
  ) {
    return null;
  }

  const byteNumbers =
    (1 << 24) | (redNumber << 16) | (greenNumber << 8) | blueNumber;

  return '#' + byteNumbers.toString(16).slice(1).toUpperCase();
}

console.log(rgbToHexadecimal('rgb(0, 0, 0)')); // "#000000" 
console.log(rgbToHexadecimal('rgb(16, 16, 16)')); // "#101010" 
console.log(rgbToHexadecimal('rgb(128, 128, 128)')); // "#808080" 
console.log(rgbToHexadecimal('rgb(245, 255, 255)')); // "#F5FFFF"
console.log(rgbToHexadecimal('rgb(2.55, 10.17, 123.876)')); // "#020A7B"

JavaScript code:

function parseFloat(value) {
  if (!value || Number.isNaN(value)) return -1;

  return Number.parseFloat(value);
}

function isRgbNumber(numberColor) {
  if (numberColor !== 0 && !numberColor) return false;

  const MIN_NUMBER_COLOR = 0;
  const MAX_NUMBER_COLOR = 255;

  return numberColor >= MIN_NUMBER_COLOR && numberColor <= MAX_NUMBER_COLOR;
}

function rgbToHexadecimal(rgbColor) {
  const LENGTH_OF_RGB_COLOR = 3;

  const regexToRemoveCharacters = /[A-Z()\s]/gi;
  const redGreenAndBlueNumbers = rgbColor
    .toLowerCase()
    .replace(regexToRemoveCharacters, '')
    .split(',');

  if (redGreenAndBlueNumbers.length !== LENGTH_OF_RGB_COLOR) return null;

  const [red, green, blue] = redGreenAndBlueNumbers;
  const allColorsExists = !!red && !!green && !!blue;
  if (!allColorsExists) return null;

  const redNumber = parseFloat(red);
  const greenNumber = parseFloat(green);
  const blueNumber = parseFloat(blue);

  if (
    !isRgbNumber(redNumber) ||
    !isRgbNumber(greenNumber) ||
    !isRgbNumber(blueNumber)
  ) {
    return null;
  }

  const byteNumbers =
    (1 << 24) | (redNumber << 16) | (greenNumber << 8) | blueNumber;

  return '#' + byteNumbers.toString(16).slice(1).toUpperCase();
}

console.log(rgbToHexadecimal('rgb(0, 0, 0)')); // "#000000" 
console.log(rgbToHexadecimal('rgb(16, 16, 16)')); // "#101010" 
console.log(rgbToHexadecimal('rgb(128, 128, 128)')); // "#808080" 
console.log(rgbToHexadecimal('rgb(245, 255, 255)')); // "#F5FFFF"
console.log(rgbToHexadecimal('rgb(2.55, 10.17, 123.876)')); // "#020A7B"

Not the answer you're looking for? Browse other questions tagged or ask your own question.