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 | — |
Work with this pattern
Take this expression further — test it against your own data, adapt it in the builder, or read up on the syntax behind it.
Regex Tester
Test a regular expression against sample text and see every match highlighted live.
Regex Generator
Build a pattern by clicking blocks — no syntax memorisation required.
Regular Expressions Guide
What regex is, how the syntax works, and the mistakes that trip people up.
Regex Cheat Sheet
Every token, quantifier, and assertion on one printable page.
Python Regex Guide
The re module end to end — search, match, findall, groups, and substitution.
Regex Pattern Library
100+ ready-to-use patterns for email, URLs, dates, IPs, and more.