Skip to content

Instantly share code, notes, and snippets.

@olmokramer
Last active December 9, 2023 12:52
Show Gist options
  • 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
@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