/^/
MediumWeb5 min read

HTML Attribute Regex

Validates a single HTML attribute, matching a boolean attribute name on its own (like disabled), or a name=value pair using double-quoted, single-quoted, or unquoted attribute values.

#html#attribute#web#markup#parsing

Regex Pattern

^[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?$

Pattern Breakdown

Hover over a token to see what it does.

^[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?$
TokenMeaning
^Anchors the match to the start of the string
[a-zA-Z_:]The attribute name must start with a letter, underscore, or colon
[-a-zA-Z0-9_:.]*The rest of the attribute name may contain letters, digits, hyphens, underscores, colons, or dots (covering names like data-id or ng-if)
(?:Start of a non-capturing group for the optional attribute value
\s*=\s*An equals sign for the value assignment, with optional surrounding whitespace
"[^"]*"A double-quoted attribute value: any characters except a double quote
'[^']*'A single-quoted attribute value: any characters except a single quote
[^\s"'=<>`]+An unquoted attribute value: one or more characters excluding whitespace and the characters HTML forbids in unquoted values
)?$Closes the value group, marks the whole value assignment as optional, and anchors to the end of the string

Detailed Explanation

What it does

This pattern recognizes a single HTML attribute exactly as it would appear inside a tag's opening bracket: a bare boolean attribute name like disabled or readonly, or a name followed by an equals sign and a value written with double quotes, single quotes, or (per the HTML5 spec) no quotes at all.

Why it works

HTML attribute names start with a letter, underscore, or colon and may continue with letters, digits, hyphens, dots, underscores, or colons, which the two leading character classes encode directly. The optional non-capturing group then covers the three legal ways to write a value: quoted with ", quoted with ', or bare and unquoted, and the unquoted alternative explicitly excludes whitespace and the ambiguous characters ('"=<>`) that the HTML5 spec forbids in an unquoted value, while the whole value group is marked optional with ? so boolean attributes without any value still match.

Common use cases

  • Validating a single attribute token while writing a lightweight HTML template linter or formatter
  • Extracting attribute name/value pairs when parsing simplified or trusted HTML fragments
  • Checking that a dynamically constructed attribute string is well-formed before injecting it into markup
  • Building autocomplete or diagnostics tooling for JSX/HTML attribute syntax

Edge cases

  • A boolean attribute with no value at all, like disabled or required, is valid since the value group is entirely optional
  • An attribute name containing hyphens and colons, like data-id or xlink:href, is valid because both characters are permitted in the name
  • An unquoted numeric value, like tabindex=3, is valid under the HTML5 unquoted-value rule this pattern implements
  • A value containing a literal space without quotes, like alt=hello world, is rejected because the unquoted-value alternative excludes whitespace

Limitations

  • Does not validate that the attribute name is a real, spec-defined HTML attribute (it accepts any syntactically shaped name, including invented ones)
  • Does not handle HTML entities inside attribute values (e.g. &quot; or &amp;) beyond treating them as ordinary characters
  • Only validates one attribute at a time; parsing a full tag with multiple attributes requires splitting or scanning separately, ideally with a real HTML parser

Interactive Tester

Edit the pattern or text below — matching runs live in your browser.

disabled id="main" class='btn btn-primary'

Test Cases

Editable — add your own inputs to see if they pass.

InputExpectedResult
Pass
Pass
Pass
Pass
Pass
Pass
Pass
Pass

Language Variants

Production-ready examples in 12 languages.

const htmlAttributeRegex = /^[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'=<>`]+))?$/;
console.log(htmlAttributeRegex.test('data-value=123')); // true

Common Mistakes

Forgetting that HTML5 allows unquoted attribute values entirely, and only matching quoted values with name="value" or name='value'

Fix: Add a third alternative for unquoted values, excluding whitespace and the characters ' " = < > ` as the HTML5 spec requires

Making the value group mandatory instead of optional, which incorrectly rejects valid boolean attributes like disabled or checked

Fix: Wrap the entire `=value` portion in a non-capturing group with a trailing ? to make it optional

Allowing a bare = with nothing after it to match, e.g. by using * instead of + inside the unquoted-value alternative

Fix: Require at least one character with + in the unquoted-value class so attr= alone (with no value) is correctly rejected

Performance Notes

  • All character classes are simple and non-overlapping, so matching runs in linear time with no catastrophic backtracking
  • The optional value group only attempts the three value alternatives when an '=' is actually present, avoiding wasted work for boolean attributes
  • Fast enough to validate every attribute while linting large HTML templates or JSX-like syntax in real time

Browser Compatibility

EngineSupportedNotes
ChromeYes
FirefoxYes
SafariYes
EdgeYes
Node.jsYes