33

Given a string of a valid CSS color value:

  • #fff
  • #ffffff
  • white
  • rgb(255, 255, 255)

I need to get an array of numbers of the following format: [R, G, B]

What is the most efficient way of doing this in JavaScript (assuming a major browser)?

Trident D'Gao
  • 18,973
  • 19
  • 95
  • 159
  • 2
    There are some small libraries available, for example: https://github.com/deanm/css-color-parser-js – user2012787 Jan 26 '13 at 01:09
  • @Timmmm Why would I want to port that code when a browser exposes a perfectly good CSS colour parser itself?! – Alnitak Apr 21 '20 at 13:06
  • Because it doesn't expose it directly, though admittedly the `div` trick is probably acceptable for most situations. OP did ask for the *most efficient* way though which is almost certainly parsing it yourself. – Timmmm Apr 21 '20 at 13:09

12 Answers12

36
function parseColor(input) {
    var m;

Obviously, the numeric values will be easier to parse than names. So we do those first.

    m = input.match(/^#([0-9a-f]{3})$/i)[1];
    if( m) {
        // in three-character format, each value is multiplied by 0x11 to give an
        // even scale from 0x00 to 0xff
        return [
            parseInt(m.charAt(0),16)*0x11,
            parseInt(m.charAt(1),16)*0x11,
            parseInt(m.charAt(2),16)*0x11
        ];
    }

That's one. Now for the full six-digit format:

    m = input.match(/^#([0-9a-f]{6})$/i)[1];
    if( m) {
        return [
            parseInt(m.substr(0,2),16),
            parseInt(m.substr(2,2),16),
            parseInt(m.substr(4,2),16)
        ];
    }

And now for rgb() format:

    m = input.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( m) {
        return [m[1],m[2],m[3]];
    }

Optionally, you can also add support for rgba format, and even hsl/hsla if you add an HSL2RGB conversion function.

Finally, the named colours.

    return ({
        "red":[255,0,0],
        "yellow":[255,255,0],
        // ... and so on. Yes, you have to define ALL the colour codes.
    })[input];

And close the function:

}

Actually, I don't know why I bothered writing all that. I just noticed you specified "assuming a major browser", I'm assuming that also means "up-to-date"? If so...

function parseColor(input) {
    var div = document.createElement('div'), m;
    div.style.color = input;
    m = getComputedStyle(div).color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( m) return [m[1],m[2],m[3]];
    else throw new Error("Colour "+input+" could not be parsed.");
}

An up-to-date browser will convert any given colour to rgb() format in its computed style. Just get it back, and read it out.

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • 1
    If the regex doesn't match, it won't have any values in the returned array, so accessing the [1]th element of the array will raise an error. You'll want to access that element after checking if m is not null. – Nimphious Jun 17 '12 at 01:46
  • That's true. Maybe do `m = ({massive colour map here})[input]; if( m) return m; return [0,0,0];`. Or throw an error from that function, since to get this condition none of the tests should match. – Niet the Dark Absol Jun 17 '12 at 01:48
  • Also the regex match for the rgba style also returns the [0] element of the array, which means it would output something like: ['rgb(5,10,15)', '5', '10', '15'], so you'd want to make sure to only return the 1st, 2nd and 3rd elements in a new array, and omit the 0th. – Nimphious Jun 17 '12 at 01:51
  • 1
    @Kolink, "I don't know why I bothered writing all that." hmm... because you want to be famous and live forever? :) Thank you for the reply! – Trident D'Gao Jun 17 '12 at 02:03
  • `/foo/.test('bar')` == `null`. `/foo/.test('bar')[1]` == `null[1]`, this will raise an exception. If you keep the `m = input.match(/^#([0-9a-f]{3})$/i)[1];` line instead of checking if m is null first, the function will break if the input is not in `#xxx` format. – Nimphious Jun 17 '12 at 02:04
  • 2
    Sorry to pester you with corrections, but you reverted my fix there without even considering why I did it in the first place. – Nimphious Jun 17 '12 at 02:10
  • The answer as currently written will throw errors. (Regex match returns null if no match, and null[1] isn't valid.) Fix is to change `m = input.match(...)[1];` to just `m = input.match(...);`, and then change `parseInt(m...` to `parseInt(m[1]...`. (Or @pondlife @darkajax @mike-d perhaps you could provide a better fix than my edit you rejected.) – medmunds Apr 10 '13 at 17:32
  • rgba is also possible. – polkovnikov.ph Oct 28 '16 at 15:52
  • @HaoCS While your edit is appreciated, please note that the `/i` modifier on the regexes makes adding `A-F` redundant. – Niet the Dark Absol Dec 07 '16 at 13:15
  • No, it doesn't. In Chrome, if you put in "red", you'll get back "red" instead of "rgb(255, 0, 0)" like in other browsers. :-( Otherwise, all will return rgb() notation, that's simple. – ygoe Dec 29 '17 at 09:53
  • discussion here https://stackoverflow.com/a/10971090/62255 about best rgb[a] string to array parser – jedierikb Mar 09 '18 at 17:32
  • Like many regex-based solutions, this one seems unnecessarily complex. Below solution by F.Hauri is the one I'll use. It is simpler, easier to understand and debug, and probably more efficient (though in most cases that is less important). – Ragnar Apr 01 '21 at 08:40
25

For HTML5 compatible browsers I write a single pixel into a <canvas> using the specified value, and read back the rgba quad.

For performance I memoize this function so that repeated calls for the same colour string don't have to perform the canvas operations.

EDIT updated for ES6 and to remove jQuery dependency

EDIT (1j01) added invalid color detection, and a function that supports passing a fallback color

let memoize = function(factory, ctx) {
    var cache = {};
    return function(key) {
        if (!(key in cache)) {
            cache[key] = factory.call(ctx, key);
        }
        return cache[key];
    };
};

let colorToRGBA = (function() {
    var canvas = document.createElement('canvas');
    canvas.width = canvas.height = 1;
    var ctx = canvas.getContext('2d');

    return memoize(function(col) {
        ctx.clearRect(0, 0, 1, 1);
        // In order to detect invalid values,
        // we can't rely on col being in the same format as what fillStyle is computed as,
        // but we can ask it to implicitly compute a normalized value twice and compare.
        ctx.fillStyle = '#000';
        ctx.fillStyle = col;
        var computed = ctx.fillStyle;
        ctx.fillStyle = '#fff';
        ctx.fillStyle = col;
        if (computed !== ctx.fillStyle) {
            return; // invalid color
        }
        ctx.fillRect(0, 0, 1, 1);
        return [ ... ctx.getImageData(0, 0, 1, 1).data ];
    });
})();

colorToRGBA('white') // [255, 255, 255, 255]
colorToRGBA('blah') // undefined

let colorOrFallbackColorToRGBA = (color, fallbackColor)=> {
    // Don't short-circuit getting the fallback RGBA -
    // it's already memoized, and we want to show an error
    // if the fallback color is invalid even if the main color is valid
    var fallbackRGBA = colorToRGBA(fallbackColor);
    if (!fallbackRGBA) {
        throw new Error(`Invalid fallbackColor ${
            fallbackColor != null ? JSON.stringify(fallbackColor) : fallbackColor
        }`);
    }
    return colorToRGBA(color) || fallbackRGBA;
};

colorOrFallbackColorToRGBA('white', 'transparent') // [255, 255, 255, 255]
colorOrFallbackColorToRGBA('blah', 'transparent') // [0, 0, 0, 0]
1j01
  • 3,714
  • 2
  • 29
  • 30
Alnitak
  • 334,560
  • 70
  • 407
  • 495
  • 1
    This is [tag:jQuery], not [tag:javascript]! – F. Hauri - Give Up GitHub Jul 24 '17 at 14:20
  • 1
    @F.Hauri the only jQuery specific function here is `$.makeArray`, and that's only used because the `Array` constructor is broken (in the way it treats a single value as a length, but multiple values as initial values) – Alnitak Jul 24 '17 at 15:10
  • 1
    @F.Hauri and I've now updated it to remove that dependency – Alnitak Jul 24 '17 at 15:16
  • 1
    Way to go by adding memoize. A nice touch implementing it goes a long way to making this a very complete answer! – Mathias Apr 14 '18 at 03:22
  • @Timmmm care to elaborate? NB: the `colorOrFallbackColorToRGBA` was an addition by someone else. – Alnitak Apr 21 '20 at 13:00
  • 1
    OP asked for a fast way to do this. Creating a canvas is going to be insanely slower than just parsing it. Memoising is a bad workaround to hide that it is slow. If you want to avoid writing the parser yourself (it is reasonably complicated) then Niet the Dark Absol's `div` solution will be much faster than `canvas`. – Timmmm Apr 21 '20 at 13:07
  • @Timmmm this code is actually pretty damned fast. It was used in production on a substantial JS visualisation platform where we needed to be able to convert a large number of CSS colours into RGBA pixels (for direct blitting into a canvas' pixel array) at high speed. – Alnitak Apr 21 '20 at 13:10
  • @Timmmm note also the comments on Niet's answer reporting that `getComputedStyle()` might return just `red` if that was what was specified, and it also fails to return the Alpha value. – Alnitak Apr 21 '20 at 13:13
  • Oh, any my canvas is created precisely _once_ regardless of how many times the function is called, whereas Niet's revised answer creates a new `
    ` for every invocation.
    – Alnitak Apr 21 '20 at 13:18
  • Right but Niet's answer could easily be changed to create a single div once. And your code is only fast because you memoise the results! How fast is it if I call it for every possible colour? Good point about `red` though. – Timmmm Apr 21 '20 at 13:26
24

Quicker and more efficient way

In addition to @NiettheDarkAbsol 's correct answer, there are some aspects:

  • backgroundColor could be rgb( 3 values ) or rgba( 4 values)

  • match function is nice but using regular expression is expensive! Whenever possible, prefer split instead.

This function is simplier and quicker:

function parseColor(input) {
    return input.split("(")[1].split(")")[0].split(",");
}

Ok returned values are still strings, and they contains unwanted spaces, but if used in mathematical expression, they would work correctly!

At all I prefer this anyway: They may be included as is:

var bgColors = document.getElementById('myDiv').
                 backgroundColor.split("(")[1].split(")")[0].split(",");

Support #RnGnBn form (IEx) as suggested by Emile Bergeron's comment

There is a small and quick function working with rgb(r,g,b), rgba(r,g,b,a), #RGB, #RRGGBB and #RRRGGGBBB:

function parseColor(input) {
    if (input.substr(0,1)=="#") {
    var collen=(input.length-1)/3;
    var fact=[17,1,0.062272][collen-1];
    return [
        Math.round(parseInt(input.substr(1,collen),16)*fact),
        Math.round(parseInt(input.substr(1+collen,collen),16)*fact),
        Math.round(parseInt(input.substr(1+2*collen,collen),16)*fact)
    ];
    }
    else return input.split("(")[1].split(")")[0].split(",").map(x=>+x);
}

Demo

function parseColor(input) {
    if (input.substr(0,1)=="#") {
    var collen=(input.length-1)/3;
    var fact=[17,1,0.062272][collen-1];
    return [
        Math.round(parseInt(input.substr(1,collen),16)*fact),
        Math.round(parseInt(input.substr(1+collen,collen),16)*fact),
        Math.round(parseInt(input.substr(1+2*collen,collen),16)*fact)
    ];
    }
    else return input.split("(")[1].split(")")[0].split(",").map(x=>+x);
}

[ "rgb(123,45,67)", "rgb( 123, 45 , 67 )", "rgba(123,45,67,0.5)", "#F70",
  "#FF7700", "#FFF777000", "#FF8000", "#FFF800000", "#F80" ].forEach(
    function(color){
        colors=parseColor(color);
        if (colors.length<4) colors.push('1.0');
        document.getElementById('out').innerHTML+=
          '<tr><td style="background:'+color+';" />'+
          '<td>'+ colors.join('</td><td>')+'</td>'+
          '<td>parseColor("'+color+'");</td></tr>';
    }
);
th { width: 3em; }
<table id="out" style="font-family: mono;background:SlateGrey">
<tr><th></th><th>Red</th><th>Green</th><th>Blue</th><th>Alpha</th><th>Code</th></tr>
</table>
F. Hauri - Give Up GitHub
  • 64,122
  • 17
  • 116
  • 137
6

Necromancing.
For anybody that actually needs it, here's fully working and feature-complete code.
Think of it as complement to the answer of "Niet the Dark Absol"
Cheers.

function parseColor(input) {
    var mm;
    var m;
    // Obviously, the numeric values will be easier to parse than names.So we do those first.
    mm = input.match(/^#?([0-9a-f]{3})$/i);
    if (mm) {
        m = mm[1];
        // in three-character format, each value is multiplied by 0x11 to give an
        // even scale from 0x00 to 0xff
        return [
            parseInt(m.charAt(0), 16) * 0x11,
            parseInt(m.charAt(1), 16) * 0x11,
            parseInt(m.charAt(2), 16) * 0x11
        ];
    }
    // That's one. Now for the full six-digit format: 
    mm = input.match(/^#?([0-9a-f]{6})$/i);
    if (mm) {
        m = mm[1];
        return [
            parseInt(m.substr(0, 2), 16),
            parseInt(m.substr(2, 2), 16),
            parseInt(m.substr(4, 2), 16)
        ];
    }
    // And now for rgb() format:
    var mm = input.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if (mm) {
        return [mm[1], mm[2], mm[3]];
    }
    // https://www.w3schools.com/colors/colors_names.asp
    // https://en.wikipedia.org/wiki/Web_colors
    // http://www.colors.commutercreative.com/grid/
    var webColors = {
        "AliceBlue": "#F0F8FF",
        "AntiqueWhite": "#FAEBD7",
        "Aqua": "#00FFFF",
        "Aquamarine": "#7FFFD4",
        "Azure": "#F0FFFF",
        "Beige": "#F5F5DC",
        "Bisque": "#FFE4C4",
        "Black": "#000000",
        "BlanchedAlmond": "#FFEBCD",
        "Blue": "#0000FF",
        "BlueViolet": "#8A2BE2",
        "Brown": "#A52A2A",
        "BurlyWood": "#DEB887",
        "CadetBlue": "#5F9EA0",
        "Chartreuse": "#7FFF00",
        "Chocolate": "#D2691E",
        "Coral": "#FF7F50",
        "CornflowerBlue": "#6495ED",
        "Cornsilk": "#FFF8DC",
        "Crimson": "#DC143C",
        "Cyan": "#00FFFF",
        "DarkBlue": "#00008B",
        "DarkCyan": "#008B8B",
        "DarkGoldenRod": "#B8860B",
        "DarkGray": "#A9A9A9",
        "DarkGrey": "#A9A9A9",
        "DarkGreen": "#006400",
        "DarkKhaki": "#BDB76B",
        "DarkMagenta": "#8B008B",
        "DarkOliveGreen": "#556B2F",
        "DarkOrange": "#FF8C00",
        "DarkOrchid": "#9932CC",
        "DarkRed": "#8B0000",
        "DarkSalmon": "#E9967A",
        "DarkSeaGreen": "#8FBC8F",
        "DarkSlateBlue": "#483D8B",
        "DarkSlateGray": "#2F4F4F",
        "DarkSlateGrey": "#2F4F4F",
        "DarkTurquoise": "#00CED1",
        "DarkViolet": "#9400D3",
        "DeepPink": "#FF1493",
        "DeepSkyBlue": "#00BFFF",
        "DimGray": "#696969",
        "DimGrey": "#696969",
        "DodgerBlue": "#1E90FF",
        "FireBrick": "#B22222",
        "FloralWhite": "#FFFAF0",
        "ForestGreen": "#228B22",
        "Fuchsia": "#FF00FF",
        "Gainsboro": "#DCDCDC",
        "GhostWhite": "#F8F8FF",
        "Gold": "#FFD700",
        "GoldenRod": "#DAA520",
        "Gray": "#808080",
        "Grey": "#808080",
        "Green": "#008000",
        "GreenYellow": "#ADFF2F",
        "HoneyDew": "#F0FFF0",
        "HotPink": "#FF69B4",
        "IndianRed ": "#CD5C5C",
        "Indigo ": "#4B0082",
        "Ivory": "#FFFFF0",
        "Khaki": "#F0E68C",
        "Lavender": "#E6E6FA",
        "LavenderBlush": "#FFF0F5",
        "LawnGreen": "#7CFC00",
        "LemonChiffon": "#FFFACD",
        "LightBlue": "#ADD8E6",
        "LightCoral": "#F08080",
        "LightCyan": "#E0FFFF",
        "LightGoldenRodYellow": "#FAFAD2",
        "LightGray": "#D3D3D3",
        "LightGrey": "#D3D3D3",
        "LightGreen": "#90EE90",
        "LightPink": "#FFB6C1",
        "LightSalmon": "#FFA07A",
        "LightSeaGreen": "#20B2AA",
        "LightSkyBlue": "#87CEFA",
        "LightSlateGray": "#778899",
        "LightSlateGrey": "#778899",
        "LightSteelBlue": "#B0C4DE",
        "LightYellow": "#FFFFE0",
        "Lime": "#00FF00",
        "LimeGreen": "#32CD32",
        "Linen": "#FAF0E6",
        "Magenta": "#FF00FF",
        "Maroon": "#800000",
        "MediumAquaMarine": "#66CDAA",
        "MediumBlue": "#0000CD",
        "MediumOrchid": "#BA55D3",
        "MediumPurple": "#9370DB",
        "MediumSeaGreen": "#3CB371",
        "MediumSlateBlue": "#7B68EE",
        "MediumSpringGreen": "#00FA9A",
        "MediumTurquoise": "#48D1CC",
        "MediumVioletRed": "#C71585",
        "MidnightBlue": "#191970",
        "MintCream": "#F5FFFA",
        "MistyRose": "#FFE4E1",
        "Moccasin": "#FFE4B5",
        "NavajoWhite": "#FFDEAD",
        "Navy": "#000080",
        "OldLace": "#FDF5E6",
        "Olive": "#808000",
        "OliveDrab": "#6B8E23",
        "Orange": "#FFA500",
        "OrangeRed": "#FF4500",
        "Orchid": "#DA70D6",
        "PaleGoldenRod": "#EEE8AA",
        "PaleGreen": "#98FB98",
        "PaleTurquoise": "#AFEEEE",
        "PaleVioletRed": "#DB7093",
        "PapayaWhip": "#FFEFD5",
        "PeachPuff": "#FFDAB9",
        "Peru": "#CD853F",
        "Pink": "#FFC0CB",
        "Plum": "#DDA0DD",
        "PowderBlue": "#B0E0E6",
        "Purple": "#800080",
        "RebeccaPurple": "#663399",
        "Red": "#FF0000",
        "RosyBrown": "#BC8F8F",
        "RoyalBlue": "#4169E1",
        "SaddleBrown": "#8B4513",
        "Salmon": "#FA8072",
        "SandyBrown": "#F4A460",
        "SeaGreen": "#2E8B57",
        "SeaShell": "#FFF5EE",
        "Sienna": "#A0522D",
        "Silver": "#C0C0C0",
        "SkyBlue": "#87CEEB",
        "SlateBlue": "#6A5ACD",
        "SlateGray": "#708090",
        "SlateGrey": "#708090",
        "Snow": "#FFFAFA",
        "SpringGreen": "#00FF7F",
        "SteelBlue": "#4682B4",
        "Tan": "#D2B48C",
        "Teal": "#008080",
        "Thistle": "#D8BFD8",
        "Tomato": "#FF6347",
        "Turquoise": "#40E0D0",
        "Violet": "#EE82EE",
        "Wheat": "#F5DEB3",
        "White": "#FFFFFF",
        "WhiteSmoke": "#F5F5F5",
        "Yellow": "#FFFF00",
        "YellowGreen": "#9ACD32"
    };
    for (var p in webColors) {
        webColors[p.toLowerCase()] = webColors[p];
    }
    var wc = webColors[input.toLowerCase()];
    if (wc != null)
        return parseColor(wc);
    console.log(input);
    throw Error("'" + input + "' is not a valid color...");
}
// parseColor("steelblue");
parseColor("SteelBlue");
// JSON.stringify(webColors, null, 2);
// JSON.stringify(lcWebColors, null, 2);
//# sourceMappingURL=colorInfluence.js.map
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
  • Some notes: 1. Use `let` not `var`; or better yet you can use `const` a lot in here. 2. You don't need to declare variables at the top of your function anymore. It's not 1998. 3. Your lowercasing logic is all wrong. E.g. `BLUE` won't work but it should. You should lowercase the colour on *lookup*, don't just add all the lowercase names to the map. I.e. `const we = webColors[input.toLowerCase()]`. – Timmmm Apr 21 '20 at 12:43
  • 1
    Props for being the only person to actually include the colour names though. – Timmmm Apr 21 '20 at 12:43
5

While kennebec has mostly completed Kolink's answer, there are some improvements to be made. Firstly, we can support hsla and rgba, and in doing so it is best to always return an alpha value. Another minor improvement is made by applying the trim method to the incoming argument string.

function parseColor(color) {
    color = color.trim().toLowerCase();
    color = _colorsByName[color] || color;
    var hex3 = color.match(/^#([0-9a-f]{3})$/i);
    if (hex3) {
        hex3 = hex3[1];
        return [
            parseInt(hex3.charAt(0),16)*0x11,
            parseInt(hex3.charAt(1),16)*0x11,
            parseInt(hex3.charAt(2),16)*0x11, 1
        ];
    }
    var hex6 = color.match(/^#([0-9a-f]{6})$/i);
    if (hex6) {
        hex6 = hex6[1];
        return [
            parseInt(hex6.substr(0,2),16),
            parseInt(hex6.substr(2,2),16),
            parseInt(hex6.substr(4,2),16), 1
        ];
    }
    var rgba = color.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+.*\d*)\s*\)$/i) || color.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( rgba ) {
        return [rgba[1],rgba[2],rgba[3], rgba[4]===undefined?1:rgba[4]];
    }
    var rgb = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
    if( rgb ) {
        return [rgb[1],rgb[2],rgb[3],1];
    }
    if(color.indexOf('hsl')== 0)
        return _hslToRgb(color);
}

function _hslToRgb(hsl){
    if(typeof hsl== 'string'){
        hsl= hsl.match(/(\d+(\.\d+)?)/g);
    }
    var sub, h= hsl[0]/360, s= hsl[1]/100, l= hsl[2]/100, a = hsl[3]===undefined?1:hsl[3], t1, t2, t3, rgb, val;
    if(s== 0){
        val= Math.round(l*255);
        rgb= [val, val, val, a];
    }
    else{
        if(l<0.5)
            t2= l*(1 + s);
        else
            t2= l + s - l*s;
        t1 = 2*l - t2;
        rgb = [0, 0, 0];
        for(var i=0; i<3; i++){
            t3 = h + 1/3 * -(i - 1);
            t3 < 0 && t3++;
            t3 > 1 && t3--;
            if (6 * t3 < 1)
                val= t1 + (t2 - t1) * 6 * t3;
            else if (2 * t3 < 1)
                val= t2;
            else if (3*t3<2)
                val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
            else
                val= t1;
            rgb[i] = Math.round(val*255);
        }
    }
    rgb.push(a);
    return rgb;
}
var _colorsByName = {aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",
    black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",
    chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",
    darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkkhaki:"#bdb76b",
    darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",
    darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",
    deepskyblue:"#00bfff",dimgray:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",
    fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",
    greenyellow:"#adff2f",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred :"#cd5c5c",indigo :"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",
    lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",
    lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",
    lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",
    limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",
    mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",
    mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",
    navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",
    orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",
    peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",
    royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",
    silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",
    tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",
    whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"
};
Adam Lockhart
  • 1,165
  • 1
  • 10
  • 13
3

// This will return a [red.green,blue] decimal array for the samples you posted, plus rgb percentages.

// It ignores transparency, hsl and the extended set of color names most browsers support:

function getRgb(c){
    c= c.toLowerCase();
    if (/^[a-z]+$/.test(c)){
        var colornames={
            aqua:'#00ffff', black:'#000000', blue:'#0000ff', fuchsia:'#ff00ff',
            gray:'#808080', green:'#008000', lime:'#00ff00', maroon:'#800000',
            navy:'#000080', olive:'#808000', orange:'#ffa500', purple:'#800080',
            red:'#ff0000', silver:'#c0c0c0', teal:'#008080', white:'#ffffff',
            yellow:'#ffff00'
        }
        c= colornames[c];
    }
    if(/^#([a-f0-9]{3}){1,2}$/.test(c)){
        if(c.length== 4){
            c= '#'+[c[1], c[1], c[2], c[2], c[3], c[3]].join('');
        }
        c= '0x'+c.substring(1);
        return [(c>>16)&255, (c>>8)&255, c&255];
    }
    else if(c.indexOf('rgb')== 0){
        c= c.match(/\d+(\.\d+)?%?/g);
        if(c){
            for(var i= 0;i<3;i++){
                if(c[i].indexOf('%')!= -1){
                         c[i]= Math.round(parseFloat(c[i])*2.55);
                    }
                if(c[i]<0) c[i]= 0;
                if(c[i]>255) c[i]= 255;
            }
            return c;
        }
    }
}

//This version will return a [red.green,blue] decimal array for most color strings, ignoring transparency.

function getRgb2(c){
    c= c.toLowerCase();
    var colornames={
        aliceblue:'#f0f8ff', antiquewhite:'#faebd7', aqua:'#00ffff',
        aquamarine:'#7fffd4', azure:'#f0ffff', beige:'#f5f5dc',
        bisque:'#ffe4c4', black:'#000000', blanchedalmond:'#ffebcd',
        blue:'#0000ff', blueviolet:'#8a2be2', brown:'#a52a2a',
        burlywood:'#deb887', cadetblue:'#5f9ea0', chartreuse:'#7fff00',
        chocolate:'#d2691e', coral:'#ff7f50', cornflowerblue:'#6495ed',
        cornsilk:'#fff8dc', crimson:'#dc143c', cyan:'#00ffff',
        darkblue:'#00008b', darkcyan:'#008b8b', darkgoldenrod:'#b8860b',
        darkgray:'#a9a9a9', darkgreen:'#006400', darkkhaki:'#bdb76b',
        darkmagenta:'#8b008b', darkolivegreen:'#556b2f', darkorange:'#ff8c00',
        darkorchid:'#9932cc', darkred:'#8b0000', darksalmon:'#e9967a',
        darkseagreen:'#8fbc8f', darkslateblue:'#483d8b', darkslategray:'#2f4f4f',
        darkturquoise:'#00ced1', darkviolet:'#9400d3', deeppink:'#ff1493',
        deepskyblue:'#00bfff', dimgray:'#696969', dodgerblue:'#1e90ff',
        firebrick:'#b22222', floralwhite:'#fffaf0',
        forestgreen:'#228b22', fuchsia:'#ff00ff', gainsboro:'#dcdcdc',
        ghostwhite:'#f8f8ff', gold:'#ffd700', goldenrod:'#daa520', gray:'#808080',
        green:'#008000', greenyellow:'#adff2f', honeydew:'#f0fff0',
        hotpink:'#ff69b4', indianred:'#cd5c5c', indigo:'#4b0082',
        ivory:'#fffff0', khaki:'#f0e68c', lavender:'#e6e6fa',
        lavenderblush:'#fff0f5', lawngreen:'#7cfc00', lemonchiffon:'#fffacd',
        lightblue:'#add8e6', lightcoral:'#f08080', lightcyan:'#e0ffff',
        lightgoldenrodyellow:'#fafad2', lightgray:'#d3d3d3', lightgreen:'#90ee90',
        lightpink:'#ffb6c1', lightsalmon:'#ffa07a', lightseagreen:'#20b2aa',
        lightskyblue:'#87cefa', lightslategray:'#778899', lightsteelblue:'#b0c4de',
        lightyellow:'#ffffe0', lime:'#00ff00', limegreen:'#32cd32', linen:'#faf0e6',
        magenta:'#ff00ff', maroon:'#800000', mediumaquamarine:'#66cdaa',
        mediumblue:'#0000cd', mediumorchid:'#ba55d3', mediumpurple:'#9370db',
        mediumseagreen:'#3cb371', mediumslateblue:'#7b68ee',
        mediumspringgreen:'#00fa9a', mediumturquoise:'#48d1cc',
        mediumvioletred:'#c71585', midnightblue:'#191970', mintcream:'#f5fffa',
        mistyrose:'#ffe4e1', moccasin:'#ffe4b5', navajowhite:'#ffdead',
        navy:'#000080', oldlace:'#fdf5e6', olive:'#808000', olivedrab:'#6b8e23',
        orange:'#ffa500', orangered:'#ff4500', orchid:'#da70d6',
        alegoldenrod:'#eee8aa', palegreen:'#98fb98', paleturquoise:'#afeeee',
        palevioletred:'#db7093', papayawhip:'#ffefd5', peachpuff:'#ffdab9',
        peru:'#cd853f', pink:'#ffc0cb', plum:'#dda0dd', powderblue:'#b0e0e6',
        purple:'#800080', red:'#ff0000', rosybrown:'#bc8f8f', royalblue:'#4169e1',
        saddlebrown:'#8b4513', salmon:'#fa8072', sandybrown:'#f4a460',
        seagreen:'#2e8b57', seashell:'#fff5ee', sienna:'#a0522d',
        silver:'#c0c0c0', skyblue:'#87ceeb', slateblue:'#6a5acd',
        slategray:'#708090', snow:'#fffafa', springgreen:'#00ff7f',
        steelblue:'#4682b4', tan:'#d2b48c', teal:'#008080', thistle:'#d8bfd8',
        tomato:'#ff6347', turquoise:'#40e0d0', violet:'#ee82ee', wheat:'#f5deb3',
        white:'#ffffff', whitesmoke:'#f5f5f5', yellow:'#ffff00', yellowgreen:'#9acd32'
    }
    if (/^[a-z]+$/.test(c)){
        c= colornames[c];
    }
    if(/^#([a-f0-9]{3}){1,2}$/.test(c)){
        if(c.length== 4){
            c= '#'+[c[1], c[1], c[2], c[2], c[3], c[3]].join('');
        }
        c= '0x'+c.substring(1);
        return [(c>>16)&255, (c>>8)&255, c&255];
    }
    if(c.indexOf('hsl')== 0) return hslToRgb(c);
    else{
        c= c.match(/\d+(\.\d+)?%?/g);
        if(c){
            for(var i= 0;i<3;i++){
                if(c[i].indexOf('%')!= -1) c[i]= parseFloat(c[i])*2.55;
                c[i]= Math.round(c[i]);
                if(c[i]<0) c[i]= 0;
                if(c[i]>255) c[i]= 255;
            }
            return c;
        }
    }
    function hslToRgb(hsl){
        if(typeof hsl== 'string'){
            hsl= hsl.match(/(\d+(\.\d+)?)/g);
        }
        var sub, h= hsl[0]/360, s= hsl[1]/100, l= hsl[2]/100,
        t1, t2, t3, rgb, val;
        if(s== 0){
            val= Math.round(l*255);
            rgb= [val, val, val];
        }
        else{
            if(l<0.5)   t2= l*(1 + s);
            else t2= l + s - l*s;
            t1= 2*l - t2;
            rgb= [0, 0, 0];
            for(var i= 0;i<3;i++){
                t3= h + 1/3*-(i - 1);
                t3<0 && t3++;
                t3>1 && t3--;
                if(6*t3<1) val= t1 +(t2 - t1)*6*t3;
                else if(2*t3<1) val= t2;
                else if(3*t3<2) val= t1 +(t2 - t1)*(2/3 - t3)*6;
                else val= t1;
                rgb[i]= Math.round(val*255);
            }
        }
        return rgb;
    }
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
1

Simplifying @NicolasL's answer (which in turn was inspired by @Niet_the_Dark_Absol's)

I got this simple and short, browser-based solution:

function parseCssColor(str) {
    const div = document.createElement("div");
    document.body.appendChild(div);
    div.style.color = str;
    const res = getComputedStyle(div).color.match(/[\.\d]+/g).map(Number);
    div.remove();
    return res;
}


parseCssColor("lightblue")  // [173, 216, 230]
parseCssColor("#663399")    // [102, 51, 153]
parseCssColor("#aa11bb22")  // [170, 17, 187, 0.133]
0

For both type of colors hsl and rgb this works:

input.replace(/[a-z%\s\(\)]/g,'').split(',')
jscripter
  • 840
  • 1
  • 11
  • 23
0

Trying @Niet_the_Dark_Absol's answer with this beautiful getComputedStyle hack, I've been unable to make it work until appending to the DOM the created element (Chrome 69 and Firefox 75).

As I also wanted to be able to handle the alpha channel value (transparency), I modified the Regex and returned result.

Here is my function if it can be of any help for anyone:

function colorToRgbParser(cssColor) {
  const div = document.createElement('div');
  div.id = 'for-computed-style';

  div.style.color = cssColor;

  // appending the created element to the DOM
  document.querySelector('body').appendChild(div);

  const match = getComputedStyle(div).color.match(/^rgba?\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d\.\d)\s*)?\)$/i);

  // removing element from the DOM
  document.querySelector('#for-computed-style').remove();

  if (match) {
    // match[0] is regex complete match (e.g. "rgb(0,0,0)"), not a regex capturing group
    let parsedColor = {
      r: match[1],
      g: match[2],
      b: match[3]
    };
    if (match[4]) { // if alpha channel is present
      parsedColor.a = match[4];
    }
    return parsedColor;
  } else {
    throw new Error(`Color ${cssColor} could not be parsed.`);
  }
}
NicolasL
  • 53
  • 1
  • 8
  • this is actually a great solution, but you could save a whole lot of code if you just used the regex /\d+/g (then apply .map(Number) if you wish) – Nitsan BenHanoch Jul 29 '21 at 02:19
0

I came here for the same problem. But after reading all these approaches (and where they are wrong or not working in all cases) I decided to go for a library.

In addition to parsing a color most of the time you want to do something with it anyway.

If like mine your definition of "efficient" is "with less errors and working out of the box" I recommend using chroma.js.

Install it with npm install chroma-js (not chrome-js, not chroma)

chroma('pink').darken().saturate(2).rgb()
Scheintod
  • 7,953
  • 9
  • 42
  • 61
0

/**
 * Created on 1401/6/11 (2022/9/2).
 * @author {@link https://mirismaili.github.io S. Mahdi Mir-Ismaili}
 */

class Color {
  #r = 0
  #g = 0
  #b = 0
  #a = 1
  #red = 0
  #green = 0
  #blue = 0
  #alpha = 100
  #alpha255 = 255
  
  /**
   * @param {RgbInputParams|[number?,number?,number?,number?]|string|number} rgbInputParamsOrRgbArrayOrHexFormatOrRed
   * @param {number} green
   * @param {number} blue
   * @param {number} alpha
   */
  constructor ({
    red = 0, green = 0, blue = 0, alpha = 100, r = red / 255, g = green / 255, b = blue / 255, a = alpha / 100,
  } = {}) { // noinspection JSCheckFunctionSignatures
    this.set(...arguments)
  }
  
  /**
   * @param {RgbInputParams|[number?,number?,number?,number?]|string|number} rgbInputParamsOrRgbArrayOrHexFormatOrRed
   * @param {number} green
   * @param {number} blue
   * @param {number} alpha
   */
  set ({
    red = 0, green = 0, blue = 0, alpha = 100, r = red / 255, g = green / 255, b = blue / 255, a = alpha / 100,
  } = {}) {
    const input = arguments[0] ?? {r: 0, g: 0, b: 0, a: 1}
    const inputType = typeof input
    
    if (inputType === 'object') {
      if (input instanceof Array) {
        this.rgb = input
        return this
      }
      
      this.r = r
      this.g = g
      this.b = b
      this.a = a
      return this
    }
    
    if (inputType === 'number') { // noinspection JSValidateTypes
      this.RGB = arguments
      return this
    }
    
    if (inputType !== 'string') throw Error(`Unsupported color format: ${input}`)
    
    if (input.startsWith('#')) { // hex (`#123456`) format:
      this.hex = input
      return this
    }
    
    const match = input.match(/^rgba?\s*\(\s*(.+)\s*\)$/i) // https://regex101.com/r/TvtRCL/1
    if (match) { // `rgb[a](...)` format:
      const values = match[1].split(/[ ,/]+/)
      this.RGB = values.slice(0, 3).map(v => +v)
      const aa = values[3]
      if (!aa) this.a = 1
      else if (aa.endsWith('%')) this.alpha = +aa.slice(0, -1)
      else this.a = +aa
      return this
    }
    
    if (input in WEB_COLORS) {
      this.name = input
      return this
    }
    throw Error(`Unsupported color format: ${input}`)
  }
  
  get r () { return this.#r }
  get g () { return this.#g }
  get b () { return this.#b }
  get a () { return this.#a }
  get red () { return this.#red }
  get green () { return this.#green }
  get blue () { return this.#blue }
  get alpha () { return this.#alpha }
  get alpha255 () { return this.#alpha255 }
  get rgb () { return [this.#r, this.#g, this.#b, this.#a] }
  get RGB () { return [this.#red, this.#green, this.#blue, this.#alpha] }
  get value () { // `>>> 0` is to make the result unsigned. See: https://stackoverflow.com/a/54030756/5318303
    return (this.#red << 24 >>> 0) + (this.#green << 16) + (this.#blue << 8) + this.#alpha255
  }
  get hex () {
    const hex = this.value.toString(16).padStart(8, '0')
    return this.alpha255 < 255 ? `#${hex}` : `#${hex.slice(0, -2)}`
  }
  get name () {return REVERSE_WEB_COLORS[this.hex]}
  
  set r (r) {
    this.#r = r
    this.#red = Math.round(r * 255)
  }
  set g (g) {
    this.#g = g
    this.#green = Math.round(g * 255)
  }
  set b (b) {
    this.#b = b
    this.#blue = Math.round(b * 255)
  }
  set a (a) {
    this.#alpha = Math.round(a * 100)
    this.#a = a
    this.#alpha255 = Math.round(a * 255)
  }
  set red (red) {
    this.#r = red / 255
    this.#red = red
  }
  set green (green) {
    this.#g = green / 255
    this.#green = green
  }
  set blue (blue) {
    this.#b = blue / 255
    this.#blue = blue
  }
  set alpha (alpha) {
    this.#a = alpha / 100
    this.#alpha = alpha
    this.#alpha255 = Math.round(this.#a * 255)
  }
  set alpha255 (alpha255) {
    this.#a = alpha255 / 255
    this.#alpha255 = alpha255
    this.#alpha = Math.round(this.#a * 100)
  }
  set rgb ([r, g, b, a]) {
    if (typeof r === 'number') this.r = r
    if (typeof g === 'number') this.g = g
    if (typeof b === 'number') this.b = b
    if (typeof a === 'number') this.a = a
  }
  set RGB ([red, green, blue, alpha]) {
    if (typeof red === 'number') this.red = red
    if (typeof green === 'number') this.green = green
    if (typeof blue === 'number') this.blue = blue
    if (typeof alpha === 'number') this.alpha = alpha
  }
  set value (value) { // https://jsben.ch/ZJB9W
    this.alpha255 = value % 0x100
    this.blue = (value >>>= 8) % 0x100
    this.green = (value >>>= 8) % 0x100
    this.red = (value >>> 8) % 0x100
  }
  set hex (hexFormatColor) {
    let hex = hexFormatColor.slice(1)
    // noinspection FallThroughInSwitchStatementJS
    switch (hex.length) { // #123 | #1234 | #123456 | #12345678
      case 3:
        hex += 'f' // default `alpha`
      case 4:
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2] + hex[3] + hex[3]
        break
      case 6:
        hex += 'ff' // default `alpha`
      case 8:
        break
      default:
        throw Error(`Unsupported color format (${hexFormatColor}). The length of hex string must be 3 or 4 or 6 or 8.`)
    }
    this.value = parseInt(hex, 16)
  }
  set name (input) {
    const hexFormatColor = WEB_COLORS[input]
    this.value = (parseInt(hexFormatColor.slice(1), 16) << 8 >>> 0) + 0xFF
  }
  
  toString () { // noinspection JSCheckFunctionSignatures
    const hex = this.hex
    const colorName = this.name
    
    return hex + (this.alpha255 < 255
                  ? ` rgb(${this.#red} ${this.#green} ${this.#blue} / ${this.#alpha}%)`
                  : ` rgb(${this.#red} ${this.#green} ${this.#blue})`
    ) + (colorName ? ` "${colorName}"` : '')
  }
}

// Uncomment `await` in your module:
/*await*/ import('util').then((util) => {
  Color.prototype[util.inspect.custom] = function () {
    return this.toString()
  }
}).catch(() => {}) // Ignore `import` error to sure it works properly in both node and browser environments

/**
 * @typedef {Object} RgbInputParams
 * @property {number} [red=0] An integer in `[0, 255]` interval
 * @property {number} [green=0] An integer in `[0, 255]` interval
 * @property {number} [blue=0] An integer in `[0, 255]` interval
 * @property {number} [alpha=0] An integer in `[0, 100]` interval
 * @property {number} [r=red/255] An alternative for **red** channel as a number in `[0, 1]` interval
 * @property {number} [g=green/255] An alternative for **green** channel as a number in `[0, 1]` interval
 * @property {number} [b=blue/255] An alternative for **blue** channel as a number in `[0, 1]` interval
 * @property {number} [a=alpha/100] An alternative for **alpha** channel as a number in `[0, 1]` interval
 */

const WEB_COLORS = {
  black: '#000000',
  silver: '#c0c0c0',
  gray: '#808080',
  white: '#ffffff',
  maroon: '#800000',
  red: '#ff0000',
  purple: '#800080',
  fuchsia: '#ff00ff',
  green: '#008000',
  lime: '#00ff00',
  olive: '#808000',
  yellow: '#ffff00',
  navy: '#000080',
  blue: '#0000ff',
  teal: '#008080',
  aqua: '#00ffff',
  aliceblue: '#f0f8ff',
  antiquewhite: '#faebd7',
  aquamarine: '#7fffd4',
  azure: '#f0ffff',
  beige: '#f5f5dc',
  bisque: '#ffe4c4',
  blanchedalmond: '#ffebcd',
  blueviolet: '#8a2be2',
  brown: '#a52a2a',
  burlywood: '#deb887',
  cadetblue: '#5f9ea0',
  chartreuse: '#7fff00',
  chocolate: '#d2691e',
  coral: '#ff7f50',
  cornflowerblue: '#6495ed',
  cornsilk: '#fff8dc',
  crimson: '#dc143c',
  cyan: '#00ffff',
  darkblue: '#00008b',
  darkcyan: '#008b8b',
  darkgoldenrod: '#b8860b',
  darkgray: '#a9a9a9',
  darkgreen: '#006400',
  darkgrey: '#a9a9a9',
  darkkhaki: '#bdb76b',
  darkmagenta: '#8b008b',
  darkolivegreen: '#556b2f',
  darkorange: '#ff8c00',
  darkorchid: '#9932cc',
  darkred: '#8b0000',
  darksalmon: '#e9967a',
  darkseagreen: '#8fbc8f',
  darkslateblue: '#483d8b',
  darkslategray: '#2f4f4f',
  darkslategrey: '#2f4f4f',
  darkturquoise: '#00ced1',
  darkviolet: '#9400d3',
  deeppink: '#ff1493',
  deepskyblue: '#00bfff',
  dimgray: '#696969',
  dimgrey: '#696969',
  dodgerblue: '#1e90ff',
  firebrick: '#b22222',
  floralwhite: '#fffaf0',
  forestgreen: '#228b22',
  gainsboro: '#dcdcdc',
  ghostwhite: '#f8f8ff',
  gold: '#ffd700',
  goldenrod: '#daa520',
  greenyellow: '#adff2f',
  grey: '#808080',
  honeydew: '#f0fff0',
  hotpink: '#ff69b4',
  indianred: '#cd5c5c',
  indigo: '#4b0082',
  ivory: '#fffff0',
  khaki: '#f0e68c',
  lavender: '#e6e6fa',
  lavenderblush: '#fff0f5',
  lawngreen: '#7cfc00',
  lemonchiffon: '#fffacd',
  lightblue: '#add8e6',
  lightcoral: '#f08080',
  lightcyan: '#e0ffff',
  lightgoldenrodyellow: '#fafad2',
  lightgray: '#d3d3d3',
  lightgreen: '#90ee90',
  lightgrey: '#d3d3d3',
  lightpink: '#ffb6c1',
  lightsalmon: '#ffa07a',
  lightseagreen: '#20b2aa',
  lightskyblue: '#87cefa',
  lightslategray: '#778899',
  lightslategrey: '#778899',
  lightsteelblue: '#b0c4de',
  lightyellow: '#ffffe0',
  limegreen: '#32cd32',
  linen: '#faf0e6',
  magenta: '#ff00ff',
  mediumaquamarine: '#66cdaa',
  mediumblue: '#0000cd',
  mediumorchid: '#ba55d3',
  mediumpurple: '#9370db',
  mediumseagreen: '#3cb371',
  mediumslateblue: '#7b68ee',
  mediumspringgreen: '#00fa9a',
  mediumturquoise: '#48d1cc',
  mediumvioletred: '#c71585',
  midnightblue: '#191970',
  mintcream: '#f5fffa',
  mistyrose: '#ffe4e1',
  moccasin: '#ffe4b5',
  navajowhite: '#ffdead',
  oldlace: '#fdf5e6',
  olivedrab: '#6b8e23',
  orange: '#ffa500',
  orangered: '#ff4500',
  orchid: '#da70d6',
  palegoldenrod: '#eee8aa',
  palegreen: '#98fb98',
  paleturquoise: '#afeeee',
  palevioletred: '#db7093',
  papayawhip: '#ffefd5',
  peachpuff: '#ffdab9',
  peru: '#cd853f',
  pink: '#ffc0cb',
  plum: '#dda0dd',
  powderblue: '#b0e0e6',
  rosybrown: '#bc8f8f',
  royalblue: '#4169e1',
  saddlebrown: '#8b4513',
  salmon: '#fa8072',
  sandybrown: '#f4a460',
  seagreen: '#2e8b57',
  seashell: '#fff5ee',
  sienna: '#a0522d',
  skyblue: '#87ceeb',
  slateblue: '#6a5acd',
  slategray: '#708090',
  slategrey: '#708090',
  snow: '#fffafa',
  springgreen: '#00ff7f',
  steelblue: '#4682b4',
  tan: '#d2b48c',
  thistle: '#d8bfd8',
  tomato: '#ff6347',
  turquoise: '#40e0d0',
  violet: '#ee82ee',
  wheat: '#f5deb3',
  whitesmoke: '#f5f5f5',
  yellowgreen: '#9acd32',
}

const REVERSE_WEB_COLORS = Object.fromEntries(Object.entries(WEB_COLORS).map(([k, v]) => [v, k]))

new Color('#123')
new Color('#1234')
new Color('#123456')
new Color('#12345678')

new Color('rgb(32, 98, 101)')
new Color('rgb(32 98 101 / 86%)')
new Color('rgba(32 98 101 / .86)')

new Color('blue')
new Color('darkgreen')

new Color({r: 0.4, g: 0.2, b: 0.9})
new Color([0.4, 0.2, 0.9])
new Color({red: 45, green: 142, blue: 255})
new Color(45, 142, 255)

let color = new Color()
color.value = 0x12345678 // '#1234567'

// outputs:
color = new Color('#83a0bfa0')
console.log(color)
console.log(color.toString())
console.log(color.hex)
console.log(color.value)
const {r, g, b, a, red, green, blue, alpha} = color
console.log({r, g, b, a, red, green, blue, alpha})

color = new Color('#ff0000')
console.log(color)
console.log(color.toString())
console.log(color.hex)
console.log(color.rgb)
console.log(color.RGB)
console.log(color.name)

Install it as a NPM module:

npm i smart-color
import Color from 'smart-color/Color.js'

// ...
Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
-1
var input = '#FFF';
var color = input.toLowerCase();
var hex = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
var rgb = [];
if(/#/.test(color))
    if(color.length==4){
        var parsed = color.match(/\w/g);
        rgb = [
            hex.indexOf(parsed[0])*16+hex.indexOf(parsed[0]),
            hex.indexOf(parsed[1])*16+hex.indexOf(parsed[1]),
            hex.indexOf(parsed[2])*16+hex.indexOf(parsed[2])
        ]
    }else{
        var parsed = color.match(/\w{2}/g);
        rgb = [
            hex.indexOf(parsed[0][0])*16+hex.indexOf(parsed[0][1]),
            hex.indexOf(parsed[1][0])*16+hex.indexOf(parsed[1][1]),
            hex.indexOf(parsed[2][0])*16+hex.indexOf(parsed[2][1])
        ]
    }
else if(/(rgb)/.test(color))
    rgb = color.match(/\d+/g);
else{
    //Here you define all the colors, like 'blue': [0,0,255]
}

If you are trying to get an element's background-color, for example, you can use this:

var bg = getComputedStyle(myElem,null).getPropertyValue('background-color');
var rgb = match(/\d+/g).slice(0,3);
Danilo Valente
  • 11,270
  • 8
  • 53
  • 67