Which characters are valid in CSS class names/selectors?

CssCss Selectors

Css Problem Overview

What characters/symbols are allowed within the CSS class selectors?
I know that the following characters are invalid, but what characters are valid?

~ ! @ $ % ^ & * ( ) + = , . / ' ; : " ? > < [ ] \ { } | ` #

Css Solutions

Solution 1 - Css

You can check directly at the CSS grammar.

Basically1, a name must begin with an underscore (_), a hyphen (-), or a letter(az), followed by any number of hyphens, underscores, letters, or numbers. There is a catch: if the first character is a hyphen, the second character must2 be a letter or underscore, and the name must be at least 2 characters long.


In short, the previous rule translates to the following, extracted from the W3C spec.:

> In CSS, identifiers (including element names, classes, and IDs in > selectors) can contain only the characters [a-z0-9] and ISO 10646 > characters U+00A0 and higher, plus the hyphen (-) and the underscore > (_); they cannot start with a digit, or a hyphen followed by a digit. > Identifiers can also contain escaped characters and any ISO 10646 > character as a numeric code (see next item). For instance, the > identifier "B&W?" may be written as "B&W?" or "B\26 W\3F".

Identifiers beginning with a hyphen or underscore are typically reserved for browser-specific extensions, as in -moz-opacity.

1 It's all made a bit more complicated by the inclusion of escaped unicode characters (that no one really uses).

2 Note that, according to the grammar I linked, a rule starting with TWO hyphens, e.g. --indent1, is invalid. However, I'm pretty sure I've seen this in practice.

Solution 2 - Css

To my surprise most answers here are wrong. It turns out that:

Any character except NUL is allowed in CSS class names in CSS. (If CSS contains NUL (escaped or not), the result is undefined. [CSS-characters])

Mathias Bynens' answer links to explanation and demos showing how to use these names. Written down in CSS code, a class name may need escaping, but that doesn’t change the class name. E.g. an unnecessarily over-escaped representation will look different from other representations of that name, but it still refers to the same class name.

Most other (programming) languages don’t have that concept of escaping variable names (“identifiers”), so all representations of a variable have to look the same. This is not the case in CSS.

Note that in HTML there is no way to include space characters (space, tab, line feed, form feed and carriage return) in a class name attribute, because they already separate classes from each other.

So, if you need to turn a random string into a CSS class name: take care of NUL and space, and escape (accordingly for CSS or HTML). Done.

Solution 3 - Css

I’ve answered your question in-depth here: http://mathiasbynens.be/notes/css-escapes

The article also explains how to escape any character in CSS (and JavaScript), and I made a handy tool for this as well. From that page:

> If you were to give an element an ID value of !@$%^&*()_+-=,./';:"?><[]{}|#</code>, the selector would look like this: > > **CSS:** > ><!-- language: lang-css --> > > <style> > #\~\!\@\$\%\^\&\*\(\)\_\+-\=\,\.\/\'\;\:\"\?\>\<\[\]\\\{\}\|\# > { > background: hotpink; > } > > > JavaScript: > > > >

Solution 4 - Css

Read the W3C spec. (this is CSS 2.1, find the appropriate version for your assumption of browsers)

edit: relevant paragraph follows:

> In CSS, identifiers (including > element names, classes, and IDs in > selectors) can contain only the > characters [a-z0-9] and ISO 10646 > characters U+00A1 and higher, plus the > hyphen (-) and the underscore (_); > they cannot start with a digit, or a > hyphen followed by a digit. > Identifiers can also contain escaped > characters and any ISO 10646 character > as a numeric code (see next item). For > instance, the identifier "B&W?" may be > written as "B&W?" or "B\26 W\3F".

edit 2: as @mipadi points out in Triptych's answer, there's this caveat, also in the same webpage:

> In CSS, identifiers may begin with '-' > (dash) or '_' (underscore). Keywords > and property names beginning with '-' > or '' are reserved for > vendor-specific extensions. Such > vendor-specific extensions should have > one of the following formats: > '-' + vendor identifier + '-' + meaningful name '' + vendor identifier + '-' + meaningful name > > > Example(s): > > For example, if XYZ organization added > a property to describe the color of > the border on the East side of the > display, they might call it > -xyz-border-east-color. > > Other known examples: > -moz-box-sizing -moz-border-radius -wap-accesskey > > An initial dash or underscore is > guaranteed never to be used in a > property or keyword by any current or > future level of CSS. Thus typical CSS > implementations may not recognize such > properties and may ignore them > according to the rules for handling > parsing errors. However, because the > initial dash or underscore is part of > the grammar, CSS 2.1 implementers > should always be able to use a > CSS-conforming parser, whether or not > they support any vendor-specific > extensions. > > Authors should avoid vendor-specific > extensions

Solution 5 - Css

The complete regular expression is:

-?(?:[_a-z]|[\200-\377]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])(?:[_a-z0-9-]|[\200-\377]|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*

So all of your listed character except “-” and “_” are not allowed if used directly. But you can encode them using a backslash foo\~bar or using the unicode notation foo\7E bar.

Solution 6 - Css

For those looking for a workaround, you can use an attribute selector, for instance, if your class begins with a number. Change:

.000000-8{background:url(../../images/common/000000-0.8.png);} /* DOESN'T WORK!! */

to this:

[class="000000-8"]{background:url(../../images/common/000000-0.8.png);} /* WORKS :) */

Also, if there are multiple classes, you will need to specify them in selector or use the ~= operator:



  1. https://benfrain.com/when-and-where-you-can-use-numbers-in-id-and-class-names/
  2. https://stackoverflow.com/questions/21227702/is-there-a-workaround-to-make-css-classes-with-names-that-start-with-numbers-val
  3. https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

Solution 7 - Css

My understanding is that the underscore is technically valid. Check out:


"...errata to the specification published in early 2001 made underscores legal for the first time."

The article linked above says never use them, then gives a list of browsers that don't support them, all of which are, in terms of numbers of users at least, long-redundant.

Solution 8 - Css

For HTML5/CSS3 classes and IDs can start with numbers.

Solution 9 - Css

We can use all characters as class name. Even like # and . Just we have to escape it with \.

.test\.123 {
  color: red;

.test\#123 {
  color: blue;

.test\@123 {
  color: green;

.test\<123 {
  color: brown;

.test\`123 {
  color: purple;

.test\~123 {
  color: tomato;

<div class="test.123">test.123</div>
<div class="test#123">test#123</div>
<div class="test@123">test@123</div>
<div class="test<123">test<123</div>
<div class="test`123">test`123</div>
<div class="test~123">test~123</div>

Solution 10 - Css

Going off of @Triptych's answer, you can use the following 2 regex matches to make a string valid:


This is a reverse match that selects anything that isn't a letter, number, dash or underscore for easy removal.


This matches 0 or 1 dashes followed by 1 or more numbers at the beginning of a string, also for easy removal.

How I use it in PHP:

//Make alphanumeric with dashes and underscores (removes all other characters)
$class = preg_replace("/[^a-z0-9A-Z_-]/", "", $class);
//Classes only begin with an underscore or letter
$class = preg_replace("/^-*[0-9]+/", "", $class);
//Make sure the string is 2 or more characters long
return 2 <= strlen($class) ? $class : '';

Solution 11 - Css

I would not recommend to use anything except A-z, _- and 0-9, while it's just easier to code with those symbols. Also do not start classes with - while those classes are usually browser-specific flags. To avoid any issues with IDE autocompletion, less complexity when you may need to generate those class names with some other code for whatever reason. Maybe some transpiling software may not work etc. etc.

Yet CSS is quite loose on this. You can use any symbols, even emoji works.

  border: 2px solid blue;
  width: 100px;
  height: 100px;
  overflow: hidden;

<div class="😭">

enter image description here


All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDarryl HeinView Question on Stackoverflow
Solution 1 - CssKenan BanksView Answer on Stackoverflow
Solution 2 - CssRobert SiemerView Answer on Stackoverflow
Solution 3 - CssMathias BynensView Answer on Stackoverflow
Solution 4 - CssJason SView Answer on Stackoverflow
Solution 5 - CssGumboView Answer on Stackoverflow
Solution 6 - CssD.TateView Answer on Stackoverflow
Solution 7 - CssmofahaView Answer on Stackoverflow
Solution 8 - CssMariusView Answer on Stackoverflow
Solution 9 - CssdoğukanView Answer on Stackoverflow
Solution 10 - CssManny FleurmondView Answer on Stackoverflow
Solution 11 - CssLukas LiesisView Answer on Stackoverflow