Regex for hex colours: three, six and eight digit forms
The preset matches a hash followed by three or six hexadecimal digits, with a word boundary that stops it accepting a longer run. The four and eight digit alpha forms need a different pattern.
At a glance
- Built in preset
- Hex Color
- Preset pattern
- #(?:[0-9a-fA-F]{3}){1,2}\b
- Preset flags
- g and i
- Matches
- three digit and six digit forms
- Does not match
- the four and eight digit forms that carry an alpha channel
- Why the \b matters
- without it, #abcd would match as #abc and the d would be ignored
In detail
The preset is compact because it repeats a group of three rather than listing two lengths: one iteration gives the shorthand form and two give the full one. That construction is exact, so it never matches four or five digits, and the trailing word boundary is what makes it exact rather than merely greedy.
Removing that boundary would break it quietly. Against #abcd the group would fall back to one iteration, match #abc, and report success on a string that is not a valid colour in either form. With the boundary in place the fallback is rejected too, because the d that follows is a word character and there is no boundary between it and the c.
The gap is the alpha forms. CSS accepts four and eight digit colours, where the extra digits carry opacity, and the preset matches neither. A pattern that covers all four lengths has to list them longest first, because an alternation is ordered and a shorter branch listed earlier would match a prefix and stop.
As always, the pattern checks shape and not meaning. It says nothing about whether the colour is readable against its background, and a validator built on it should still be paired with a real parse if the value is going anywhere near a rendering pipeline.
Examples
const hex = /#(?:[0-9a-fA-F]{3}){1,2}\b/gi;
"Colors: #fff, #FF5733, #00aacc, #123, not #xyz or #12345g".match(hex);
// ["#fff", "#FF5733", "#00aacc", "#123"]const hex = /#(?:[0-9a-fA-F]{3}){1,2}\b/i;
hex.test("#abcd"); // false
hex.test("#12345678"); // false
// Longest branch first, because alternation is ordered.
const all = /#(?:[\da-f]{8}|[\da-f]{6}|[\da-f]{3,4})\b/gi;
"#12345678 #abcd #fff".match(all);
// ["#12345678", "#abcd", "#fff"]Things that catch people out
- The preset rejects the four and eight digit alpha forms, so a validator built on it turns away colours that CSS accepts.
- Dropping the word boundary makes #abcd match as #abc, which silently accepts a malformed value and truncates it at the same time.
- In an alternation over lengths, listing the shortest branch first makes the longer ones unreachable. Order them longest first.
Try it: Regex Tester
Type a pattern and a test string, watch every match highlight as you go, read a plain English breakdown of each token, and check the numbered and named groups it captured.
Regex Tester
LOCAL · Browser-OnlyTest and debug regular expressions with live matching and highlights
Related Regex syntax
All regex syntax →Regex for UUIDs: matching the 8-4-4-4-12 layout
The preset matches the hexadecimal layout of any UUID. Pinning it to version 4 takes two extra character classes, one for the version and one for the variant.
[a-z] ranges: code point order and the A-z bug
Ranges inside a character class run by code point, which is why [A-z] quietly includes six punctuation characters and [a-Z] is a syntax error.
Alternation: precedence and ordered choice
The pipe has the lowest precedence of any regex operator and the branches are tried in order, so ^cat|dog$ and /a|ab/ both surprise people.
Regex for ISO dates: matching YYYY-MM-DD without fake days
The preset rejects month 13 and day 32 with two alternations, and still accepts 2026-02-31. No regex can check a calendar, so parse and compare.
Regex for phone numbers, and why strict ones lose customers
Phone formatting varies by country and by habit. The built in US preset does not even match the parenthesised form in its own sample, which is the lesson.
Regex to trim whitespace, collapse runs and drop blank lines
There is no preset for this one. Four short patterns cover trimming, collapsing, per line trimming and removing blank lines, and each has a different failure.
Tools for this
- Regex Tester Free online regex tester - test and debug regular expressions with live matching and highlights
- Regex Playground Regex playground with live match highlighting, named groups, find and replace, and shareable links