CSS Class Selector Regex
Validates a single CSS class selector: a leading dot followed by a legal CSS identifier, such as .btn, .btn-primary, or .btn_2, using ASCII letters, digits, underscores, and hyphens.
Regex Pattern
^\.-?[_a-zA-Z][_a-zA-Z0-9-]*$Pattern Breakdown
Hover over a token to see what it does.
| Token | Meaning |
|---|---|
| ^ | Anchors the match to the start of the string |
| \. | A literal dot marking the start of a CSS class selector |
| -? | An optional single leading hyphen, allowed before the identifier's first letter |
| [_a-zA-Z] | The identifier itself must start with a letter or underscore |
| [_a-zA-Z0-9-]* | Zero or more letters, digits, underscores, or hyphens make up the rest of the class name |
| $ | Anchors the match to the end of the string |
Detailed Explanation
What it does
This pattern checks that a string is a single, well-formed CSS class selector: a dot followed by a name that starts with a letter or underscore (optionally preceded by one hyphen) and continues with letters, digits, underscores, or hyphens. It rejects selectors with no leading dot, names starting with a digit, and embedded spaces.
Why it works
The CSS specification allows a class name to begin with an optional single hyphen followed by a letter or underscore, then any run of letters, digits, underscores, or hyphens. The pattern mirrors that: \. anchors the required dot, -? allows the one optional leading hyphen, [_a-zA-Z] enforces a non-digit identifier start, and the trailing [_a-zA-Z0-9-]* class permits the remaining legal characters, all locked to the full string by ^/$.
Common use cases
- Validating a single class name before injecting it into a dynamically generated stylesheet
- Linting CSS-in-JS or utility-class strings for typos before they reach the browser
- Sanitizing user-configurable class names in a theming or design-system tool
- Filtering safe class tokens when building a class-name allowlist for a CMS or page builder
Edge cases
- A single leading hyphen before the identifier, like .-webkit-box, is valid and mirrors real-world vendor-prefixed utility classes
- Underscore-led names, like ._private, are valid since underscore is an allowed identifier-start character
- A name with a double leading hyphen, like .--custom, is rejected here because only one optional hyphen is permitted before the letter/underscore
- A bare word with no leading dot, like btn, is rejected since the dot is mandatory for a class selector
Limitations
- Does not support CSS escape sequences (e.g. \.foo\:hover) used to escape special characters inside class names
- Does not match multiple chained class selectors like .btn.btn-primary or combinators like .btn > .icon
- Only covers ASCII characters; real CSS identifiers can include escaped Unicode code points
Interactive Tester
Edit the pattern or text below — matching runs live in your browser.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass |
Language Variants
Production-ready examples in 12 languages.
const cssClassSelectorRegex = /^\.-?[_a-zA-Z][_a-zA-Z0-9-]*$/;
console.log(cssClassSelectorRegex.test('.btn-primary')); // trueCommon Mistakes
Forgetting to escape the leading dot, writing ^.-?[_a-zA-Z]... where the unescaped . matches any character instead of a literal dot
Fix: Escape the dot as \. so it only matches a literal period at the start of the selector
Allowing the identifier to start with a digit by writing [_a-zA-Z0-9] for the first character too
Fix: Keep the first identifier character restricted to [_a-zA-Z] (no digits), matching real CSS identifier-start rules
Assuming this pattern also matches compound or descendant selectors like .btn.active or .card .title
Fix: This pattern only validates one bare class selector; parse or split on '.' and whitespace separately for compound selectors
Performance Notes
- All quantifiers use simple, non-overlapping character classes, so matching runs in linear time with no catastrophic backtracking
- The optional -? and single required identifier-start character keep the automaton small and fast to evaluate
- Cheap enough to validate every class name in a large stylesheet or class-name allowlist without noticeable cost
Browser Compatibility
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |