Match a hex color
Match CSS hex colors in both the 3- and 6-digit forms — with the word boundary that stops #abcd from half-matching.
Last updated
Matches
- #fff
- #0a0b0f
- #FF5733
Doesn’t match
- #12
- #abcd
- 0a0b0f
Why it’s written this way
The alternation tries the 3-digit shorthand and the 6-digit long form; the trailing \b is what makes it honest. Without it, #abcd would "match" as #abc plus a stray d — with it, a 4- or 5-digit value fails outright instead of half-matching.
Case-insensitive by character class, so #FF5733 and #ff5733 both land without needing the i flag.
Edge cases to know
- →4- and 8-digit hex with alpha (#fff8, #0a0b0fcc) are rejected — add {4} and {8} alternatives if your CSS uses them.
- →It finds colors in prose too, so a Markdown heading anchor like #introduction never matches (letters g–z fail the class), but a bare hex word after # would.
- →Named colors and rgb()/oklch() functions are out of scope — this is only the # literal.
Part by part
- #
- The literal hash. It has no special meaning in regex, so it needs no escaping — unlike in a CSS selector, where it does.
- (?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})
- Two alternatives: the three-digit shorthand or the full six-digit form. Longest-first ordering matters here, and this pattern gets it wrong on purpose — see the mistakes below.
- [0-9a-fA-F]{6}
- The full form: two hex digits each for red, green and blue.
- \b
- A word boundary at the end, which is what stops #abc matching the first three characters of #abcdef.
Common mistakes
#[0-9a-fA-F]{3,6}A range accepts four and five digit values, which are not valid CSS colours at all. It also matches greedily, so it will happily consume five characters of a six-digit value if the sixth is not hex.
#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})\b#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})Without the trailing boundary, regex alternation takes the first branch that matches, so #ff8800 matches as #ff8 and leaves 800 behind. The boundary is what forces the longer branch to win.
#[0-9a-f]{6}Lowercase-only misses #FFAA00, and design tools emit uppercase as often as not. Listing both cases costs nothing and avoids a bug that only shows up on someone else's stylesheet.
Questions
Does it match eight-digit colours with an alpha channel?
No. #RRGGBBAA and the four-digit #RGBA shorthand are valid modern CSS but are not covered here — add 8 and 4 as further alternatives if your stylesheets use them, keeping the longest branch first.
Why does the shorthand form expand the way it does?
Each digit is doubled rather than padded, so #f80 means #ff8800 and not #f08000. That is why the shorthand can only express colours whose channel pairs happen to repeat.
Will it match a colour inside a longer identifier?
It can. In an id like #ff0000-highlight the colour portion matches, because the boundary sits between the 0 and the hyphen. Anchor the pattern when you are validating a value rather than scanning a stylesheet.
Does it cover named colours or rgb() notation?
No, only hex. CSS accepts named colours, rgb(), hsl(), oklch() and more, each with its own syntax — a pattern that tried to cover them all would be far harder to read than four separate ones.