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
totallyNotLizards
  • 8,489
  • 9
  • 51
  • 85
Neil
  • 7,861
  • 4
  • 53
  • 74

9 Answers9

50

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("");
Nippey
  • 4,708
  • 36
  • 44
  • I'm probably doing something wrong here, but would you check this does work please as I'm getting 0x255255255 - http://jsfiddle.net/QRk6J/1/ – Neil Oct 25 '12 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 - http://jsfiddle.net/QRk6J/2/ – Neil Oct 25 '12 at 15:27
  • Here (Opera), it works with the same var. But good to know, thanks! – Nippey Oct 25 '12 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. – user1329482 May 17 '17 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;
}
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • I don't need percentages in this case, but as percentages are used in other cases I'll +1 you. – Neil Oct 25 '12 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);

Community
  • 1
  • 1
bobobobo
  • 64,917
  • 62
  • 258
  • 363
5

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)'))
Slai
  • 22,144
  • 5
  • 45
  • 53
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}
Stack
  • 205
  • 2
  • 11
  • It supports both rgb() and rgba(). – gramcha Nov 25 '17 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 Jul 16 '21 at 02: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()
}
Sebastian
  • 21
  • 3
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('');
Vedaant Arya
  • 475
  • 6
  • 18
1

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".

0

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("");