Regex for Hexadecimal Color Code Validation — 3, 6, and 8-Digit Hex
Hex color inputs show up in theme builders, design tools, and CSS-in-JS configuration — and users paste them in every possible shape: with or without the leading #, shorthand or full length, sometimes uppercase. This guide covers the regex patterns for all common hex color formats, including the alpha-channel variants.
Hex Color Formats
- 3-digit shorthand —
#abc— each digit represents a doubled hex pair (R, G, B) - 6-digit standard —
#aabbcc— two hex digits each for red, green, blue - 4-digit shorthand with alpha —
#abcd— RGB shorthand plus one alpha digit - 8-digit with alpha —
#aabbccdd— full RGB plus a two-digit alpha channel
Basic Regex (3 or 6 Digits)
const hexColor = /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
hexColor.test('#1a2b3c'); // true
hexColor.test('1a2b3c'); // true — # is optional
hexColor.test('#abc'); // true — 3-digit shorthand
hexColor.test('#1a2b3'); // false — 5 digits is not a valid length
hexColor.test('#gghhii'); // false — g, h, i are not valid hex charactersExtended Regex with Alpha Channel (4 or 8 Digits)
CSS Color Module Level 4 supports an alpha channel appended directly to the hex string. This pattern covers all four valid lengths — 3, 4, 6, and 8 digits:
const hexColorWithAlpha = /^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{4}|[A-Fa-f0-9]{3})$/;
hexColorWithAlpha.test('#1a2b3c80'); // true — 6-digit color + 2-digit alpha
hexColorWithAlpha.test('#abcd'); // true — 3-digit color + 1-digit alpha
hexColorWithAlpha.test('#1a2b3c8'); // false — 7 digits is not validNormalizing and Expanding Shorthand Hex
Once validated, it is often useful to normalize every hex value to the full 6-digit form before storing it, so comparisons and downstream tooling stay consistent:
function normalizeHex(input) {
const value = input.replace('#', '');
if (!/^[A-Fa-f0-9]{3}$|^[A-Fa-f0-9]{6}$/.test(value)) {
throw new Error('Invalid hex color');
}
if (value.length === 3) {
return '#' + value.split('').map((c) => c + c).join('').toLowerCase();
}
return '#' + value.toLowerCase();
}
normalizeHex('#abc'); // '#aabbcc'
normalizeHex('1A2B3C'); // '#1a2b3c'Using the Pattern in a Form Field (React Example)
function ColorInput({ value, onChange }) {
const isValid = /^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(value);
return (
<div>
<input
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder="#1a2b3c"
style={{ borderColor: isValid ? '#16a34a' : '#dc2626' }}
/>
{!isValid && <span>Enter a valid hex color, e.g. #1a2b3c</span>}
</div>
);
}Common Mistakes
- Forgetting the shorthand 3-digit and 4-digit forms are valid — many patterns online only check for 6 digits
- Not making the
#optional, which rejects valid values pasted without it - Using
[0-9a-fA-F]without anchors (^/$), which lets partial matches inside longer strings pass validation - Confusing CSS named colors ("red", "tomato") with hex codes — validate those separately against a known color-name list if you need to support them
Frequently Asked Questions
The pattern ^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$ matches both 3-digit and 6-digit hex color codes with an optional leading #.
Use ^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$ to match 8-digit (RRGGBBAA) and 4-digit (RGBA shorthand) hex codes that include an alpha/transparency channel.
Each character in the 3-digit shorthand is duplicated: #abc becomes #aabbcc. In JavaScript this can be done by matching each character and repeating it twice before joining the string back together.