RGB color parser in JavaScript

February 23rd, 2006. Tagged: JavaScript

What is it

A JavaScript class that accepts a string and tries to figure out a valid color out of it. Some accepted inputs are for example:

  • rgb(0, 23, 255)
  • #336699
  • ffee66
  • fb0
  • red
  • darkblue
  • cadet blue

For more accepted inputs - see the demo.

Here's the javascript class - rgbcolor.js.

Some history / motivation

I was playing around with an idea (will post later) and I needed to get color information using the so-called computed styles. The thing is that I needed the exact amounts of Red, Green and Blue, so I needed to parse the value returned.

In FireFox when you get a computed style, it's in the format rgb(xxx, yyy, zzz)
In IE, it's #xxyyzz.
So I needed to parse both formats.

I decided to take my script one step further and make the color parsing into a seperate class. Then I added those string values - red, green, etc.

The result is something you can use, among other purposes, as a friendlier user input field.

How to use

The class is defied in a function RGBColor(). When you instantiate the class, you pass the string to be poarsed. The class has variables for the three channels - red, green and blue and methods to get the parsed value - toHex() and toRGB().

Example use:

var color = new RGBColor('darkblue');
if (color.ok) { // 'ok' is true when the parsing was a success
    // alert channels
    alert(color.r + ', ' + color.g + ', ' + color.b);
    // alert HEX and RGB
    alert(color.toHex());
    alert(color.toRGB());
}

How it works

  • The class accepts a string
  • Any leading # is stripped; spaces are stripped
  • There' s a check against a list of valid color names, such as "red" and "darkorange" and these are mapped to a Hex code
  • An array of objects is defined that have one regexp property and a function that knows what to do if the regexp find a match
  • There is a quick validation that the channel values are between 0 and 255
  • The two getters are defined - toHex() and toRGB()
  • Finally there is a function that acts as both a self-documentation and self-uinttest, where a bunch of accepted values are automatically run through the class and parsed and the result is displayed as a help text.

The idea of the array of objects containing a regexp and a handler function is Simon Willison's. He did a script to parse dates, which I used and modified to work with time entries.

In my time parser I also introduced the idea of the self-documenting regexps and the help/test function which I'm reusing here again.

All yours

Feel free to use the code for your own color picker tool or whatever you feel like. If you let me know how you use it, that would be even greater. Meanwhile any other comments are highly appreciated.

And if I may rephrase a TV ad:
Allowing your users to enter the color "Dark Khaki" - priceless! ;)

Tell your friends about this post: Facebook, Twitter, Google+

71 Responses

  1. wow… great demo!

    p.s. there is a bug on firefox when i enter the color and press ENTER
    (the page reloads and looses the input value).

  2. Excellent work! Will come in handy.

  3. Thanks, guys!

    Baldo, I’ve added a return false; onsubmit, so it’s not reloading the page. Thanks!

  4. onsubmit of the form should be something like:

    isThatAColor(document.getElementById(‘colorinput’).value;)

    so if you press enter, the color will be parsed!

  5. Thanks, Baldo, the thing is that I was just being lazy and calling the parser onblur ignoring the onsubmit. Now I changed to the onsubmit to:

    onsubmit="isThatAColor(this.elements[0].value);return false;"

    this.elements[0].value – because again I was too lazy to give the input a proper name/id
    return false; – to not submit the form after the call to the parser

    Thanks for the heads-up!

  6. Wow. I was writing a cross browser color-fader-thing and I wrote my entire RGB->HEX->RGB object and this would have been much easier!!!!

  7. Hi Cole, thanks!

    You can check the lighter version of the parser, basically without the debug stuff and without the list of named colors (khaki et al). It’s in this posting, here’s the JS

    For the color fading, I tried this once for this project, but I had the luxury of always expecting colors as HEX #aabbcc. Here’s the code if you’re curious.

    Send me a link to your implementation when you’re ready, if you don’t mind.

  8. [...] Then getting the color value back is the tricky part (as I’m writing this I just thought I could simply store it once it’s generated, duh!). So I’m using my little RGBColor library (described here) in its lightweight version (also used here) to parse the value returned by getComputedStyle() a.k.a. currentStyle in IE. [...]

  9. Hi Stoyan!

    Impressive code! *very neat and well-coded!*

    A couple of questions, though:
    What’s up with that check you do for this.r, this.g, and this.b? Example:
    this.r = (this.r 255) ? 255 : this.r);
    Personally, I would think that leaving this part out would be better. As I see it, the values can never be

  10. *Oops, I see my use of less than / greater than tags messed up the post – I’ll use HTML entities instead*

    Hi Stoyan!

    Impressive code! *very neat and well-coded!*

    A couple of questions, though:
    What’s up with that check you do for this.r, this.g, and this.b? Example:
    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
    Personally, I would think that leaving this part out would be better. As I see it, the values can never be < 0 (if someone enters a negative value, this.r, this.g, and this.b will all be undefined and this.ok will remain false). Also, if the users inputs GGG as the color (leaving r g and b defined as NaN) and one wanted to allow this, wouldn’t it be closer to change this to 255, 255, 255 instead of 0, 0, 0?
    Myself, I just commented out that “value cleanup”, so now it doesn’t allow values such as GGG or rgb(333, 1, 4).

    Two more, minor things:
    In the loops running through “simple_colors” and “color_defs”, you could add a “break” so the loop stops executing when it’s found its match.
    If you move up the white space-stripper BEFORE the check for “#”, you would also allow the user to accidentally add a space before the “#” character.

    These are all minor adjustments, though. All in all – this has got to be one of the best scripts I’ve seen *and I’ve seen a lot :-) *! Well done! Thank you very much for allowing other people to play with your script!

    Sincerely,
    Carl

  11. Addition:
    I see now that I do need to do some validation, because I don’t want to allow for example:
    “greene”
    or
    “rgb(10, 999, 10)”
    to be accepted as colors. *I see how one might choose to allow these values, with some adjustments perhaps – but my choice is to disallow them*

    So, the cleanup I use now is:
    if (isNaN(this.r) || isNaN(this.g) || isNaN(this.b) || this.r>255 || this.g>255 || this.b>255) this.ok = false;

    Also, I didn’t want to allow for example:
    “#abcdefa”
    so I changed the substring call:
    if (color_string.charAt(0) == ‘#’) { // remove # if any
    color_string = color_string.substr(1);
    }

    Anyway, I just thought I’d leave a little note about the minor modifications I made, in case anyone else would like to try them. It’s just a matter of taste, I guess – what one wants to allow as input…

    Thanks again for the great script!

    /Carl

  12. Thanks for all your comments, Carl. I appreciate it.

  13. Thanks a lot. Very useful script.

  14. I’ve just added:

    if (color_string == null)
    color_string = “”;

    after:
    this.ok = false;

    Cheers

  15. This has saved me countless hours of pain and helped me achieve my deadline. I came down to the wire and experienced browser incompatibility with the way the color was being returned in FireFox versus IE. Using this helped me get my code out on time!

    Thanks You!
    Tom Bruinsma

  16. Great job guys… Thank for you work…

  17. Appreciate the module. From both a design and efficiency standpoint, the simple_colors hash and the “getter” functions should be implemented through the RGBColor prototype, i.e.

    RGBColor.prototype.simple_colors = {
    aliceblue: ‘f0f8ff’,

    }

    And best of all, they are trivial changes to make.

  18. This is a simple obvious little change. Where you have this:

    for (var key in simple_colors) {
    if (color_string == key) {
    color_string = simple_colors[key];
    }
    }
    // emd of simple type-in colors

    This would be much better:
    if (simple_colors[color_string]) {
    color_string = simple_colors[color_string];
    }

    You don’t need the loop at all. It may make only a small difference
    to this particular script, but if you often use this technique
    (unnecessarily searching arrays to see if a key exists), you can make your scripts simpler and faster this easy.

    Thanks… this is just what I needed for an idea I wanted to try.
    robert

  19. Thanks, Robert!

  20. RGB colors are not clipped according to the CSS, so values above 255 ARE PERMITTED and should pass validation. It would therefore be unwise to disallow them in the code.

    Cf:

    http://www.w3.org/TR/2000/REC-DOM-Level-2-Style-20001113/css.html#CSS-RGBColor

  21. The values are clipped in CSS3:
    http://www.w3.org/TR/css3-color/#rgb-color

  22. Wow This class is very good. :-)

  23. First of all my thanks to you, i have been searching for this script for a long time.. You made my Script….

    Fan of Don Lapre
    larisa@larisajoyreilly.com

  24. Hi,

    A nice implementation – thanks!

    As a suggestion, how about putting the ‘color_defs’ structure outside of the object/function to be initialised on startup as a global. Just a bit neater and faster perhaps?

    Cheers,

    Alex

  25. Very useful !
    Thanks !

  26. Good work!

    I’m using this for a website I launched this weekend at http://www.poundcolor.com.

    Thanks again!

  27. Great, great, great!

    I spent like 2 hours or sth trying to figure out what’s wrong with my code, just to find out Opera and Firefox returns it in different format, ehh browsers…

    Thanks for your work!

  28. [...] This javascript library solves the problem. http://www.phpied.com/rgb-color-parser-in-javascript/ [...]

  29. [...] use rgb color parser [...]

  30. pleas would you tell me how i can get pixel color in javascript ?and thank you verymuch…

  31. A nice implementation – thanks!

    As a suggestion, how about putting the ‘color_defs’ structure outside of the object/function to be initialised on startup as a global. Just a bit neater and faster perhaps?

  32. Rgex expression for color for RGB format

  33. This is just what I was looking for, as I plan to be capturing set values (often in color format) as a test.
    No offense, but as robust as this is, it’s still not complete.
    It needs RGB as percentage values, RGBA, HSL, HSLA, and those as percentage values.
    Also, running it through the Javascript Lint seems to help performance some. There are a few minor errors that it caught that mostly go unnoticed due to the very loose nature of Javascript.

  34. [...] I found numerous bits of code to convert between hex and decimal triplets, and one bit of code that tries to be more comprehensive. Even that code fails with hsl() and hsla() values, not to mention the fact that it’s a large chunk of code with a huge lookup table to handle the various colour names that could be used. [...]

  35. An different approach to this problem is the one I’ve posted on my blog:

    http://www.peppertop.com/blog/?p=69

    The code was written specifically for a XUL application running on Firefox 3, and will need some significant effort to make it work cross-browser, but it might provide a good starting point for someone.

    It uses the browser itself to parse any colour definitions that it doesn’t understand, so it handles any CSS that the browser itself handles. In the case of Firefox 3 this means that even hsl() and hsla() formats work.

  36. Thanks for this… I rewrote it in python to use server-side: http://gregdingle.com/code/rgbcolor.py.txt .

  37. Cool, thanks for sharing Greg!

  38. Hi….nice stuff. One minor quibble: you do this…

    for (var key in simple_colors) {
    if (color_string == key) {
    color_string = simple_colors[key];
    }
    }

    when the thing is already a hash table, so you just look it up rather than iterating the list:

    var tmp = simple_colors[color_string]
    if (tmp)
    color_string = tmp;

    I know, computers are fast and bandwidth is cheap, but still… :)

  39. Ha oops I just noticed someone else (another Robert, no less!) said the same thing. Sorry for the redundancy.

  40. Thank you I was having so much trouble with color compatibility with firefox and ie.
    I’m putting your script out as is into my color selector on my website

  41. [...] Re: Get background color from IE in rgb format? teresni wrote: > Thanks, but I don’t want to hardcode the rgb values in my code. I was > hoping for some attribute I could access or parameter I could pass to > an existing method that would return the current background color as an > rgb value rather than as the color name. I haven’t tried it, but you could look at http://www.phpied.com/rgb-color-parser-in-javascript/ [...]

  42. Where did you get your color list?
    You should use the color list at http://www.w3.org/TR/SVG/types.html#ColorKeywords

    Robert’s suggestion is very nice, it should be put in as it cuts the script time by 1/3.

  43. Exactly what I was looking for. Thanks a lot for sharing the code. I’m using it right away :)

  44. I’ve got a pretty good tool to convert hex to rgb and convert rgb to hex :)
    Pretty cool!
    David

  45. I actually also needed the reverse functionality of this. That is, to read the color in hex/rgb values and give the answer to the user in the form he understands.

    I did the necessary changes mentioned in the comments, added some colors names from the w3c page, and modified the script a bit to add a functionality to convert hex/rgb to simple color names as well – so the class is sort of complete now :) .

    It’s uploaded at this location for anyone to use:
    http://piyushsoni.com/scripts/rgbcolor.js

    Hope this helps someone out there. I can be reached at piyush_soni@yahoo.com if someone wants to criticize, or thank me.

    Thanks a lot again Stoyan for this great work !

  46. I’m using this in conjunction with CvsGraphCtx. In IE it’s throws an error on this line:

    channels = processor(bits);

    This can be fixed with this:

    var channels = processor(bits);

    Strange error but I thought I’d share it.

  47. Thanks for the library! It worked mostly just fine for my purposes. I had to extend it a little bit. I also made “toHex” more robust. You can find enhanced version of “toHex” here:
    http://gist.github.com/474238

    Kieran: I think that’s due to the fact that variables are treated global by default. “channels” overrides some global CvsGraphCtx depends upon. As you mentioned, adding “var” there fixes the issue.

  48. Thanks for this. Javascript was changing the css color correctly in all my browsers except Opera. Being able to check the HEX and RGB values of the color has fixed the problem.

  49. As already mentioned, CSS 2.1 and 3 permits values more then 255 for color components, but also permits negative values and values specified in percents (255=100%) which too may be higher then 100%. So if somebody wants to have a strict CSS compliance, (s)he should modify this script accordingly.

  50. Thank you for this very nice class. I’m using it with GelForm’s CrayonBox color picker (http://gelform.com/crayonbox-jquery-plugin/) to get the RGB values so I can calculate the gray value (.299R + .587G + .114B) and then choose a light or dark foreground color for the selection indicator. Very handy.

  51. As an experiment, I added this method to the class:

    this.toGrayLevel = function () {
    return (this.r*299 + this.g*587 + this.b*114)/1000;
    }

    Seems to work.

  52. This is great! I definitely think the reverse is a very useful – and perhaps has a wider application of uses?

  53. Thanks for schooling me on Javascript color parsers!

  54. Hello may I quote some of the material from this site if I reference you with a link back to your site?

  55. Hi, Neat post. There’s a problem with your website in internet explorer, could test this? IE still is the marketplace leader and a large portion of people will omit your magnificent writing due to this problem.

  56. Hey very nice site!! Man .. Beautiful .. Wonderful .. I will bookmark your site and take the feeds additionally?I’m glad to seek out so many helpful information here within the put up, we want develop more techniques in this regard, thank you for sharing. . . . . .

  57. minecraft…

    [...]RGB color parser in JavaScript / Stoyan’s phpied.com[...]…

  58. lds temple…

    [...]RGB color parser in JavaScript / Stoyan’s phpied.com[...]…

  59. ebay gift card codes hack…

    [...]RGB color parser in JavaScript / Stoyan’s phpied.com[...]…

  60. This is very helpful, thanks. I added support for alpha values with rgba(r, g, b, a): http://pastebin.com/YrNFJXSN

  61. That works excellent, Really helpful.

    Thanks a lot

    Farid

  62. Can I simply say what a relief to find somebody who actually is aware of what theyre speaking about on the internet. You undoubtedly know easy methods to carry an issue to gentle and make it important. More folks need to learn this and understand this aspect of the story. I cant imagine youre no more standard since you definitely have the gift.

  63. Thanks for the script!
    How I use it: after assigning a background-color to an object (e.g. #aabbcc) if I want to compare it, but if(obj.style.backgroundColor==’#aabbcc’) did not work because the browser returns rgb(…,…,…) so I used your script.

    var color = new RGBColor(obj.style.backgroundColor);
    if(color.toHex()==’#aabbcc’) {

    }

    THANKS!

  64. [...] First things first, grab the awesome RGBColor class here. [...]

  65. Somebody in essence help for making vitally content We would state. That’s the new We used your internet site web site and so a lot? My partner and i shocked with all the investigation you have made to make this specific submit outstanding. Superb approach!

  66. Wow, fantastic blog format! How lengthy have you ever been blogging for? you made running a blog glance easy. The entire glance of your site is excellent, let alone the content material!

  67. Stoyan are you going to publish this script to your Github account? This is very useful, but the initial script has a lot of issues and people are adding functionality which is getting difficult to scrape together as this script grows.

    Issues that I’m aware of:

    1. Simple color list is not using http://www.w3.org/TR/css3-color/#svg-color. There are missing colors (“grays” are there, “greys” are not), nonstandard colors (feldspar, lightslateblue, violetred), and incorrect color values (looks like OCR issue?) (mediumpurple standard: 9370DB, stoyan’s: 9370D8, palevioletred standard: DB7093, stoyan’s: D87093).

    2. The variable “channels” is undeclared before being used.

    3. There is an unnecessary loop at for (var key in simple_colors). Change the loop to a lookup: color_string = simple_colors[color_string] || color_string;

  68. Hi Stoyan.

    I created a test in which I employed the fixes, unrolled the loops and doubled the speed of the program.

    http://jsperf.com/stoyan-s-rgbcolor-js

    Enjoy!

  69. Simply want to say your article is as astonishing. The clearness in your publish is just spectacular and that i could think
    you are an expert on this subject. Well along with your permission let me to
    grab your RSS feed to keep up to date with forthcoming post.
    Thanks 1,000,000 and please continue the rewarding work.

  70. Hi Stoyan.

    That is a very good work. I was looking for something like that and here it is, thanks to you and the other guys who made it better. Is there a final version with the fixes and suggestions ?

    It would be nice to have all the good stuff together.

    Regards.

Leave a Reply