Skip to content

Instantly share code, notes, and snippets.

@olmokramer
Last active December 9, 2023 12:52
Show Gist options
  • Star 33 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save olmokramer/82ccce673f86db7cda5e to your computer and use it in GitHub Desktop.
Save olmokramer/82ccce673f86db7cda5e to your computer and use it in GitHub Desktop.
Regex for CSS colors: hex, rgb(a), hsl(a)
/(#([0-9a-f]{3}){1,2}|(rgba|hsla)\(\d{1,3}%?(,\s?\d{1,3}%?){2},\s?(1|0?\.\d+)\)|(rgb|hsl)\(\d{1,3}%?(,\s?\d{1,3}%?\)){2})/i
@tombigel
Copy link

this code does not recognize opacity of 0 and there is a bug with rgb/hsl detection.
Here is a fixed revision:

/(#([0-9a-f]{3}){1,2}|(rgba|hsla)\(\d{1,3}%?(,\s?\d{1,3}%?){2},\s?(1|0|0?\.\d+)\)|(rgb|hsl)\(\d{1,3}%?(,\s?\d{1,3}%?){2}\))/i

Copy link

ghost commented Dec 23, 2015

/(#([0-9a-f]{3}){1,2}|(rgba|hsla)\(\d{1,3}%?(,\s?\d{1,3}%?){2},\s?(1|0?\.\d+)\)|(rgb|hsl)\(\d{1,3}%?(,\s?\d{1,3}%?\)){2})/i
/(#([0-9a-f]{3}){1,2}|(rgba|hsla)\(\d{1,3}%?(,\s?\d{1,3}%?){2},\s?(1|0|0?\.\d+)\)|(rgb|hsl)\(\d{1,3}%?(,\s?\d{1,3}%?){2}\))/i

Second regexp (by tombigel) might be shrank to this one without any functional change:

/(#([\da-f]{3}){1,2}|(rgb|hsl)a\((\d{1,3}%?,\s?){3}(1|0?\.\d+)\)|(rgb|hsl)\(\d{1,3}%?(,\s?\d{1,3}%?){2}\))/i

But anyway, it is wrong.
Even considering fixed parenthesis.

Foremost, you can't set percent value to rgb(…) or rgba(…) color (like rgba(15%, 65%, 208, 0.45) ← this is wrong).
On the other side, you can set alpha-channel of rgba(…) or hsla(…) to more than 1 (e.g. 2 or 999), but it is not allowed here
…and within parentheses there could be multiple (0 or more) space signs after each comma.

I'm not talking about bad memory management (use of capturing groups (…) instead of non-capturing groups (?:…)).


So, I have two regexps for you.
Use simple one, if you need to find a definitely correct HEX/RGB(A)/HSL(A) color value among random text (limitations are set by its initial correctness):

/(#[\d\w]+|\w+\((?:\d+%?(?:,\s)*){3}(?:\d*\.?\d+)?\))/i

…or use complex one instead, if you need to find (or not) one (or several) HEX/RGB(A)/HSL(A) color value(s) that has to be verified:

/(#(?:[\da-f]{3}){1,2}|rgb\((?:\d{1,3},\s*){2}\d{1,3}\)|rgba\((?:\d{1,3},\s*){3}\d*\.?\d+\)|hsl\(\d{1,3}(?:,\s*\d{1,3}%){2}\)|hsla\(\d{1,3}(?:,\s*\d{1,3}%){2},\s*\d*\.?\d+\))/gi

@widget-
Copy link

widget- commented Mar 16, 2017

A bit late to the party but it showed up on Google so I'm guessing other people are using this still.

I noticed @ghost's version was picking up CSS ID selectors in CSS files, so I modified it to be a bit more strict.

This one passes every valid example on the MDN Color document:

/(#(?:[0-9a-f]{2}){2,4}|#[0-9a-f]{3}|(?:rgba?|hsla?)\((?:\d+%?(?:deg|rad|grad|turn)?(?:,|\s)+){2,3}[\s\/]*[\d\.]+%?\))/i

Unfortunately it also catches ones that MDN says are invalid but I don't think checking for mixed periods and percents is a good regex use.

Explanation:

  /(
        #(?:[0-9a-f]{2}){2,4}               Match #ARGB, #RRGGBB, or #AARRGGBB
     |                                   or
        #[0-9a-f]{3}                        Match #RGB
     |                                   or
        (?:rgba?|hsla?)                     Match hsl, rgb, hsla, or rgba
        \(                                  Match (
           (
              ?:\d+%?(?:deg|rad|grad|turn)?    Match 0, 0%, 00%, 0deg, 0rad, etc.
              (?:,|\s)+                        Match a comma and/or space to separate them
           ){2,3}                           Repeat 2 or 3 times
           [\s\/]*[\d\.]+%?                 Match the last value, period and slash allowed
        \)                                  Match )
  )/

@verysmallrock
Copy link

Good stuff, @widget. I used yours, but I added (^[a-zA-Z]+$) to catch the CSS color keywords (e.g. AliceBlue). My final regex looks like this:

/(^[a-zA-Z]+$)|(#(?:[0-9a-f]{2}){2,4}|#[0-9a-f]{3}|(?:rgba?|hsla?)\((?:\d+%?(?:deg|rad|grad|turn)?(?:,|\s)+){2,3}[\s\/]*[\d\.]+%?\))/i

@the94air
Copy link

the94air commented Apr 30, 2017

@verysmallrock this is better

/^(#(?:[0-9a-f]{2}){2,4}|#[0-9a-f]{3}|(?:rgba?|hsla?)\((?:\d+%?(?:deg|rad|grad|turn)?(?:,|\s)+){2,3}[\s\/]*[\d\.]+%?\))$/i

http://stackoverflow.com/questions/43706082/validation-hex-and-rgba-colors-using-regex-in-php

@HatScripts
Copy link

HatScripts commented May 3, 2017

@the94air Just so you know, that's the same as the one @widget- posted but with ^ and $ added.

Also, it can be simplified slightly:

^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((\d+%?(deg|rad|grad|turn)?[,\s]+){2,3}[\s\/]*[\d\.]+%?\))$

Also, for readability I prefer to check whether it's a hex color outside of the regex.

E.g. with PHP:

function is_valid_color($color) {
    if ($color[0] === "#") {
        $color = substr($color, 1);
        return in_array(strlen($color), [3, 4, 6, 8]) && ctype_xdigit($color);
    } else {
        return preg_match("/^(rgb|hsl)a?\((\d+%?(deg|rad|grad|turn)?[,\s]+){2,3}[\s\/]*[\d\.]+%?\)$/i", $color);
    }
}

And that's easily portable to other languages, e.g. JavaScript:

function isValidColor(color) {
    if (color.charAt(0) === "#") {
        color = color.substring(1)
        return [3, 4, 6, 8].indexOf(color.length) > -1 && !isNaN(parseInt(color, 16))
    } else {
        return /^(rgb|hsl)a?\((\d+%?(deg|rad|grad|turn)?[,\s]+){2,3}[\s\/]*[\d\.]+%?\)$/i.test(color)
    }
}

@lemnis
Copy link

lemnis commented Aug 12, 2017

Negative numbers aren't supported in the above regex and I don't know when you can use an angle in a CSS color

So I change the regex a bit, beneath regex should support all possible color values.

^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))$

Tested against:

#f00
#ff0000
rgb(255,0,0)
rgb(100%, 0%, 0%)
rgb(300,0,0)
rgb(255,-10,0)
rgb(110%, 0%, 0%)
rgba(255,0,0,1)
rgba(100%,0%,0%,1)
rgba(0,0,255,0.5)
rgba(100%, 50%, 0%, 0.1)
hsl(0, 100%, 50%)
hsl(120, 100%, 50%)
hsl(120, 75%, 75%)
hsl(120, 100%, 50%)
hsla(120, 100%, 50%, 1)
hsla(240, 100%, 50%, 0.5)
hsla(30, 100%, 50%, 0.1)
#ff00FF00
hsla(30, 100%, 50%, .1)

@lemnis
Copy link

lemnis commented Aug 28, 2017

I want to clarify my previous comment a bit, after a mention by @IamManchanda directed to me at foundation/foundation-sites#10589. My regex is designed to do basic check against SASS colors. The regex should be valid against:

If you only want to support CSS3 color syntax, you should use the regex mentioned at foundation/foundation-sites#10589 (comment)

In the future someone should update the regex to add support for the full CSS Color Module Level 4.

@AndrewEQ
Copy link

AndrewEQ commented Oct 31, 2017

(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\))/i

I removed the ^ and $, then switched the 2 hex color patterns around to match my scenarios/tests...

Tests:

.selector {
	background: #ffffff url("image.png");
}
#fa132e
#fafafa
#aaeeff
#AAAfff url("image.png")
#f00
#ff0000
#ff00FF00
rgb(255,0,0)
rgb(100%, 0%, 0%)
rgb(300,0,0)
rgb(255,-10,0)
rgb(110%, 0%, 0%)
rgba(255,0,0,1)
rgba(100%,0%,0%,1)
rgba(0,0,255,0.5)
rgba(100%, 50%, 0%, 0.1)
hsl(0, 100%, 50%)
hsl(120, 100%, 50%)
hsl(120, 75%, 75%)
hsl(120, 100%, 50%)
hsla(120, 100%, 50%, 1)
hsla(240, 100%, 50%, 0.5)
hsla(30, 100%, 50%, 0.1)
hsla(30, 100%, 50%, .1)

@FlashT
Copy link

FlashT commented Jan 16, 2018

How do I convert this to just simply return html hex color? what about spaces?

@ashwinimendon
Copy link

how to validate strings like red, green, blue and so?

@RodrigoMattosoSilveira
Copy link

All invalid color expressions pass, except the last one! Sorry~~
/* Hexadecimal Colors /
'#ff00001', /
red /
'#00ff00a', /
green /
'#0000ff6', /
blue */

	/* RBBA Colors */
	'rgb(255, 0, 0, 0.3)',   /* red */
	'rgb(0, 255, 700)',   /* green */
	'rgb(0, 0, #AAA)',   /* blue */

	/* RGBA Colors */
	'rgba(255, 0, 0, 3)',   /* red with opacity */
	'rgba(0, 255, 0)',   /* green with opacity */
	'rgba(0, 0, 255, 1)',   /* blue with opacity */

	/* HSL Colors */
	'hsl(120, 100%, 500%)',   /* green */
	'hsl(120, 100%, 75)',   /* light green */
	'hsl(120, 100%, #123)',   /* dark green */
	'hsl(120,  60%, 70)',   /* pastel green */

	/* HSLA Colors */
	'hsl(120, 100%, 50%, 0.2)',   /* green with opacity */
	'hsla(120, 100%, 75%, 40)',   /* light green with opacity */
	'hsl(120, 100%, 70%, 0.6)',   /* dark green with opacity*/
	'hslv(120,  60%, 70%, 2)',   /* pastel green with opacity  */

@Prestapro
Copy link

Hello, All

I add some improve (opacity for HEX and Uppercase register):

(#(?:[0-9a-fA-F]{2,4}){2,4}|(#[0-9a-fA-F]{3})|(rgb|hsl)a?((-?\d+%?[,\s]+){2,3}\s*[\d.]+%?))

@gavinmcfarland
Copy link

how to validate strings like red, green, blue and so?

You'll need to add those strings to your regex for example at the following of your existing regex pattern. Don't forget the first | character.

|black|silver|gray|white|maroon|red|purple|fuchsia|green|lime|olive|yellow|navy|blue|teal|aqua|orange|aliceblue|antiquewhite|aquamarine|azure|beige|bisque|blanchedalmond|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|gainsboro|ghostwhite|gold|goldenrod|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|limegreen|linen|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|oldlace|olivedrab|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|thistle|tomato|turquoise|violet|wheat|whitesmoke|yellowgreen|rebeccapurple

@CharlieEtienne
Copy link

Improvement to colors names order:

(black|silver|gray|whitesmoke|maroon|red|purple|fuchsia|green|lime|olivedrab|yellow|navy|blue|teal|aquamarine|orange|aliceblue|antiquewhite|aqua|azure|beige|bisque|blanchedalmond|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|gainsboro|ghostwhite|goldenrod|gold|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavenderblush|lavender|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|limegreen|linen|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|oldlace|olive|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|thistle|tomato|turquoise|violet|wheat|white|yellowgreen|rebeccapurple)

The whitesmoke color must be before white or it is never found. (Same thing for lavenderblush, goldenrod, aquamarine...)

@SaulGarza
Copy link

SaulGarza commented Aug 23, 2019

This was great for finding my colors in my project!

I put it all together and made the colors match whole words, it was capturing redux

(#(?:[0-9a-f]{ 2 }){ 2,4 }|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[d\.]+%?\)|\b(black|silver|gray|whitesmoke|maroon|red|purple|fuchsia|green|lime|olivedrab|yellow|navy|blue|teal|aquamarine|orange|aliceblue|antiquewhite|aqua|azure|beige|bisque|blanchedalmond|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|gainsboro|ghostwhite|goldenrod|gold|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavenderblush|lavender|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|limegreen|linen|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|oldlace|olive|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|thistle|tomato|turquoise|violet|wheat|white|yellowgreen|rebeccapurple)\b)/i

Here is the regex without the extra stuff for VSCode regex file searching:

#(?:[0-9a-f]{ 2 }){ 2,4 }|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[d\.]+%?\)|\b(black|silver|gray|whitesmoke|maroon|red|purple|fuchsia|green|lime|olivedrab|yellow|navy|blue|teal|aquamarine|orange|aliceblue|antiquewhite|aqua|azure|beige|bisque|blanchedalmond|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|gainsboro|ghostwhite|goldenrod|gold|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavenderblush|lavender|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|limegreen|linen|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|oldlace|olive|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|thistle|tomato|turquoise|violet|wheat|white|yellowgreen|rebeccapurple)\b

Edit: Left quotes in the second regex

@alsotang
Copy link

Some expressions above is not working. Below is mine:

/(#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\)|black|silver|gray|whitesmoke|maroon|red|purple|fuchsia|green|lime|olivedrab|yellow|navy|blue|teal|aquamarine|orange|aliceblue|antiquewhite|aqua|azure|beige|bisque|blanchedalmond|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|gainsboro|ghostwhite|goldenrod|gold|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavenderblush|lavender|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|limegreen|linen|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|oldlace|olive|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|thistle|tomato|turquoise|violet|wheat|white|yellowgreen|rebeccapurple)/i

combination of @AndrewEQ and @CharlieEtienne

@khalilgharbaoui
Copy link

khalilgharbaoui commented Feb 8, 2020

This is @alsotang's version with the addition of transparant and its more strict.
The named colours must be exactly that. the $ makes sure it ends that way.
Also a notable part is:

#(?:[0-9a-fA-F]{2}){2,4}$|(#[0-9a-fA-F]{3}$)|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\)$
VS
#(?:[0-9a-f]{2}){2,4}|(#[0-9a-f]{3})|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\)

/(#(?:[0-9a-fA-F]{2}){2,4}$|(#[0-9a-fA-F]{3}$)|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\)$|black$|silver$|gray$|whitesmoke$|maroon$|red$|purple$|fuchsia$|green$|lime$|olivedrab$|yellow$|navy$|blue$|teal$|aquamarine$|orange$|aliceblue$|antiquewhite$|aqua$|azure$|beige$|bisque$|blanchedalmond$|blueviolet$|brown$|burlywood$|cadetblue$|chartreuse$|chocolate$|coral$|cornflowerblue$|cornsilk$|crimson$|darkblue$|darkcyan$|darkgoldenrod$|darkgray$|darkgreen$|darkgrey$|darkkhaki$|darkmagenta$|darkolivegreen$|darkorange$|darkorchid$|darkred$|darksalmon$|darkseagreen$|darkslateblue$|darkslategray$|darkslategrey$|darkturquoise$|darkviolet$|deeppink$|deepskyblue$|dimgray$|dimgrey$|dodgerblue$|firebrick$|floralwhite$|forestgreen$|gainsboro$|ghostwhite$|goldenrod$|gold$|greenyellow$|grey$|honeydew$|hotpink$|indianred$|indigo$|ivory$|khaki$|lavenderblush$|lavender$|lawngreen$|lemonchiffon$|lightblue$|lightcoral$|lightcyan$|lightgoldenrodyellow$|lightgray$|lightgreen$|lightgrey$|lightpink$|lightsalmon$|lightseagreen$|lightskyblue$|lightslategray$|lightslategrey$|lightsteelblue$|lightyellow$|limegreen$|linen$|mediumaquamarine$|mediumblue$|mediumorchid$|mediumpurple$|mediumseagreen$|mediumslateblue$|mediumspringgreen$|mediumturquoise$|mediumvioletred$|midnightblue$|mintcream$|mistyrose$|moccasin$|navajowhite$|oldlace$|olive$|orangered$|orchid$|palegoldenrod$|palegreen$|paleturquoise$|palevioletred$|papayawhip$|peachpuff$|peru$|pink$|plum$|powderblue$|rosybrown$|royalblue$|saddlebrown$|salmon$|sandybrown$|seagreen$|seashell$|sienna$|skyblue$|slateblue$|slategray$|slategrey$|snow$|springgreen$|steelblue$|tan$|thistle$|tomato$|transparent$|turquoise$|violet$|wheat$|white$|yellowgreen$|rebeccapurple$)/i

@NicolasLetellier
Copy link

Very useful, thanks!

Just a little comment: If you include the "ignore case" flag /i at the very end of the regex, no need to check for uppercase letters ( [0-9a-f] is then enough, instead of [0-9a-fA-F]).

@frattaro
Copy link

Added currentColor, removed A-F given /i comment above.

I just tested in latest Chromium, doesn't appear to care about case-sensitivity of "currentColor" -- I thought it might be one of those weird case-sensitivity exceptions, but it isn't... thankfully.

/(#(?:[0-9a-f]{2}){2,4}$|(#[0-9a-f]{3}$)|(rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\)$|black$|silver$|gray$|whitesmoke$|maroon$|red$|purple$|fuchsia$|green$|lime$|olivedrab$|yellow$|navy$|blue$|teal$|aquamarine$|orange$|aliceblue$|antiquewhite$|aqua$|azure$|beige$|bisque$|blanchedalmond$|blueviolet$|brown$|burlywood$|cadetblue$|chartreuse$|chocolate$|coral$|cornflowerblue$|cornsilk$|crimson$|currentcolor$|darkblue$|darkcyan$|darkgoldenrod$|darkgray$|darkgreen$|darkgrey$|darkkhaki$|darkmagenta$|darkolivegreen$|darkorange$|darkorchid$|darkred$|darksalmon$|darkseagreen$|darkslateblue$|darkslategray$|darkslategrey$|darkturquoise$|darkviolet$|deeppink$|deepskyblue$|dimgray$|dimgrey$|dodgerblue$|firebrick$|floralwhite$|forestgreen$|gainsboro$|ghostwhite$|goldenrod$|gold$|greenyellow$|grey$|honeydew$|hotpink$|indianred$|indigo$|ivory$|khaki$|lavenderblush$|lavender$|lawngreen$|lemonchiffon$|lightblue$|lightcoral$|lightcyan$|lightgoldenrodyellow$|lightgray$|lightgreen$|lightgrey$|lightpink$|lightsalmon$|lightseagreen$|lightskyblue$|lightslategray$|lightslategrey$|lightsteelblue$|lightyellow$|limegreen$|linen$|mediumaquamarine$|mediumblue$|mediumorchid$|mediumpurple$|mediumseagreen$|mediumslateblue$|mediumspringgreen$|mediumturquoise$|mediumvioletred$|midnightblue$|mintcream$|mistyrose$|moccasin$|navajowhite$|oldlace$|olive$|orangered$|orchid$|palegoldenrod$|palegreen$|paleturquoise$|palevioletred$|papayawhip$|peachpuff$|peru$|pink$|plum$|powderblue$|rosybrown$|royalblue$|saddlebrown$|salmon$|sandybrown$|seagreen$|seashell$|sienna$|skyblue$|slateblue$|slategray$|slategrey$|snow$|springgreen$|steelblue$|tan$|thistle$|tomato$|transparent$|turquoise$|violet$|wheat$|white$|yellowgreen$|rebeccapurple$)/i

@hrieke
Copy link

hrieke commented May 26, 2020

License?
Thanks

@olmokramer
Copy link
Author

@hrieke My original one is public domain. Do with it whatever you want :)

@khalilgharbaoui
Copy link

khalilgharbaoui commented May 27, 2020

@olmokramer made a gem out of it and referenced the original gist in the credits section.

https://github.com/khalilgharbaoui/coloregex#credits
👍

@olmokramer
Copy link
Author

@khalilgharbaoui That's cool, always nice to see your work being used :)

Please be aware, though, that most of the regexes here still contain pretty serious bugs.

For example, a lot of patterns have a clause similar to (rgb|hsl)a?\((-?\d+%?[,\s]+){2,3}\s*[\d\.]+%?\), but this is obviously wrong for multiple reasons:

  • It accepts rgb(0, 0, 0, 0) and rgba(0, 0, 0), though rgb can only have 3 arguments and rgba must have 4 arguments.
  • It accepts rgb(0, 0%, 0%), though the arguments to rgb cannot be percentages. Joining the rgb and hsl cases was never a good idea, because rgb must always reject percentages, while hsl must accept them.
  • It accepts rgb(-1, -1, -1), though the minimum allowed value is 0.
  • It accepts rgb(999, 999, 999), though the maximum allowed value is 255.
  • It accepts hsl(0%, 0, 0), though the first argument cannot be a percentage, and the second and third argument must be percentages.

To name a few. This is not a problem if you just want to find correctly formatted colours in a body of text, but it is a problem if the regular expression is used to validate colours. The $ everywhere make it impossible to use this regex to find all colours in a body of text, though, as it will only find them at the end of the string, so the only use case that's left is validation, which, as I pointed out, the regex isn't very good at.

So I would suggest you decide what is your use case for the package, and either (or both :)

  • Replace all those $ with \b so that the regex can be used for searching again.
  • Or fix the bugs in the regex to follow the specification so that it can be used for validation.

@arnelenero
Copy link

arnelenero commented Mar 25, 2022

@olmokramer Sorry but of all the items in your bullet list above, only the last item seems to be true as regards valid values, at least nowadays (I know you posted a couple of years back)

  • rgb() and rgba() are now interchangeable, and so are hsl() and hsla(). They are now considered aliases.
  • second item is still partially true, but for different reason. rgb() accepts percentages. But only when ALL 3 color components are %.
  • rgb() accepts out of range values, including negative. The renderer just clamps it into the accepted range. This includes alpha value.

@arnelenero
Copy link

arnelenero commented Mar 25, 2022

Also I would like to point out that in general, a single regex that captures all possible values across all color spaces, hex, named colors, etc. is difficult to formulate especially if:

  • you need to retrieve values of the color components from capturing groups
  • you need to impose strict rules per color model (rgb vs. hsl)

It is still better to test the color string against different specialized patterns to determine which one matches (if any).

@xkeshav
Copy link

xkeshav commented Apr 16, 2023

none keyword allowed in latest syntax (while values are space seprated not comma separated ) hen how to capture these

following are valid css

  • rgb(none 10 20)
  • hsl(120deg none none)
  • hwb(200 none 0.5)

@Chasmical
Copy link

Chasmical commented Dec 9, 2023

Here's the regular expression I've got. It recognizes hex-colors and simple color functions. I'm using it in a remarkjs plugin to add color squares next to colors, similar to how GitHub does this: #4F82A9. It might be a bit too big, but it runs on the server for me, so it's fine.

/^(#[0-9a-fA-F]{3,4}|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}|rgb\(\s*\d*(?:\.\d*)?\s*,\s*\d*(?:\.\d*)?\s*,\s*\d*(?:\.\d*)?\s*\)|rgba\(\s*(?:\d*(?:\.\d*)?%|0)\s*,\s*(?:\d*(?:\.\d*)?%|0)\s*,\s*(?:\d*(?:\.\d*)?%|0)\s*,\s*\d*(?:\.\d*)?%?\s*\)|rgba?\(\s*\d*(?:\.\d*)?\s*\d*(?:\.\d*)?\s*\d*(?:\.\d*)?\s*(?:\/\s*\d*(?:\.\d*)?%?\s*)?\)|rgba?\(\s*(?:\d*(?:\.\d*)?%|0)\s*(?:\d*(?:\.\d*)?%|0)\s*(?:\d*(?:\.\d*)?%|0)\s*(?:\/\s*\d*(?:\.\d*)?%?\s*)?\)|hsl\(\s*\d*(?:\.\d*)?(?:deg|grad|rad|turn)?\s*,\d*(?:\.\d*)?%\s*,\s*\d*(?:\.\d*)?%\s*\)|hsla\(\s*\d*(?:\.\d*)?(?:deg|grad|rad|turn)?\s*,(?:\d*(?:\.\d*)?%|0)\s*,\s*(?:\d*(?:\.\d*)?%|0)\s*,\s*\d*(?:\.\d*)?%?\s*\)|h(?:sla?|wb)\(\s*\d*(?:\.\d*)?(?:deg|grad|rad|turn)?\s*\d*(?:\.\d*)?\s*\d*(?:\.\d*)?\s*(?:\/\s*\d*(?:\.\d*)?\s*)?\)|h(?:sla?|wb)\(\s*\d*(?:\.\d*)?(?:deg|grad|rad|turn)?\s*(?:\d*(?:\.\d*)?%|0)\s*(?:\d*(?:\.\d*)?%|0)\s*(?:\/\s*\d*(?:\.\d*)?%?\s*)?\))$/

And I'm constructing it like this (JavaScript):

const num = String.raw`\d*(?:\.\d*)?`;
const hue = `${num}(?:deg|grad|rad|turn)?`;

const colorFuncs = [
  // Hex colors: #000, #0000, #000000, #00000000
  `#[0-9a-fA-F]{3,4}`,
  `#[0-9a-fA-F]{6}`,
  `#[0-9a-fA-F]{8}`,
  // Legacy rgb/rgba: rgb(1,2,3), rgba(1,2,3,4)
  String.raw`rgb\(\s*${num}\s*,\s*${num}\s*,\s*${num}\s*\)`,
  String.raw`rgba\(\s*(?:${num}%|0)\s*,\s*(?:${num}%|0)\s*,\s*(?:${num}%|0)\s*,\s*${num}%?\s*\)`,
  // Modern rgb/rgba: rgba(1 2 3 / 0.5)
  String.raw`rgba?\(\s*${num}\s*${num}\s*${num}\s*(?:/\s*${num}%?\s*)?\)`,
  String.raw`rgba?\(\s*(?:${num}%|0)\s*(?:${num}%|0)\s*(?:${num}%|0)\s*(?:/\s*${num}%?\s*)?\)`,
  // Legacy hsl/hsla: hsl(1deg,2%,3%)
  String.raw`hsl\(\s*${hue}\s*,${num}%\s*,\s*${num}%\s*\)`,
  String.raw`hsla\(\s*${hue}\s*,(?:${num}%|0)\s*,\s*(?:${num}%|0)\s*,\s*${num}%?\s*\)`,
  // Modern hsl/hsla/hwb: hsla(1deg 2% 3% / 0.5)
  String.raw`h(?:sla?|wb)\(\s*${hue}\s*${num}\s*${num}\s*(?:/\s*${num}\s*)?\)`,
  String.raw`h(?:sla?|wb)\(\s*${hue}\s*(?:${num}%|0)\s*(?:${num}%|0)\s*(?:/\s*${num}%?\s*)?\)`,
];

export const ColorRegex = new RegExp(`^(${colorFuncs.join("|")})$`);

Here's what this regex doesn't recognize: lab(), lch(), oklab(), oklch(), color(), none keyword, <system-color> type, transparent, currentColor and named colors. Feel free to extend on this one, I'm not planning to, since for my use case I don't need that much specificity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment