1364

What characters/symbols are allowed within the CSS class selectors?

I know that the following characters are invalid, but what characters are valid?

~ ! @ $ % ^ & * ( ) + = , . / ' ; : " ? > < [ ] \ { } | ` #
Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
asked Jan 15, 2009 at 23:37
11
  • 8
    Related question: stackoverflow.com/questions/2812072/… Commented Jul 7, 2010 at 17:17
  • 43
    what about utf8 characters? Like i may type in greek Commented Nov 27, 2010 at 17:33
  • 12
    Special characters can be used in class names by escaping them - in your CSS file you can define a .hello/world class by escaping the backslash: .hello2円fworld, hello2円f world or hello\/world Commented Jun 5, 2012 at 0:18
  • 2
    Another related question, not about "syntax of names", but about "syntax of class attribute" when expressing multiple names. Commented Dec 11, 2012 at 3:41
  • 6
    You can also use emoji. npmjs.com/package/postcss-modules-emoji-classname Commented Oct 4, 2016 at 5:10

11 Answers 11

1123

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.

-?[_a-zA-Z]+[_a-zA-Z0-9-]*

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

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 "B26円 W3円F".

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.

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Jan 15, 2009 at 23:42

4 Comments

NB: The W3C says that the use of a leading '-' or '_' should be reserved for vendor-specific CSS extensions (e.g., -moz* classes implemented by Mozilla browsers).
i added sample of not starting with _ - or letter but emoji. I do NOT recommend such naming for classes yet it works. Good to know for general curiosity. stackoverflow.com/a/69963534/1737158
As of 2022, the CSS spec defines a class-name (in a .css rule's selector) as "." + ident, and the lexical scanner rules for ident specifially allow any character outside of 0x00-0x7F in a class name after an initial [_A-Za-z] character, so the [_a-zA-Z0-9-]* pattern posted here is incorrect.
This incorrectly accepts a{ as in a{ { color: red; }.
227

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]) In HTML though, permanently unassigned codepoints are not permitted either. Neither does HTML have a way to include space characters (space, tab, line feed, form feed and carriage return) in a class name attribute, because those are class lists and spaces are used here to separate class names from each other.

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.

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.

answered Jul 18, 2011 at 12:32

6 Comments

Investigating stripes CSS, they have a classname with the character ⚙
@Robert Siemer — Thank you for the note. Indeed, I did not read it all, but now I see that the answer is confusing. It looks like "Any character except NUL is allowed in CSS class names in CSS" contradicts "Neither does HTML have a way to include space characters..." In what sense a space character (for example) is allowed? As you can see, in my first comment I've just hooked your bold statement and still don't understand how can you make such a statement. Thank you if you clarify it.
@SergeyAKryukov In CSS it is legal (but not useful) to refer to class names which include spaces.—I wanted to emphasize that CSS allows "almost everything": CSS can refer to any class name you can express in HTML. And even some more... It is not a contradiction that the CSS language and the HTML language have different rules.
@Robert Siemer — Thank you for your reply. Yes, "valid but not useful" is fair enough. Do you mean that the element with the attribute class="abc def" still leaves the HTML well-formed? That would be reasonable enough, but, as I understand, you cannot even use such a class as a CSS selector, right? I guess, all you can do is read or write the value of this attribute in JavaScript, and do something with these values, not necessarily relevant to styling...
@SergeyAKryukov Sure it is well-formed. But the meaning is not that the element is in one class, but in two, as you know. I’m not aware of a way to assign an element to a class with spaces. Certainly not with the class attribute, and even JavaScript elem.classList.add('abc def') rejects the class name (at least in Chrome). Nevertheless, CSS allows selectors which apply to elements in classes with space(s). They will never be used unless you find a way to create such an element...
|
91

I’ve answered your question in-depth at CSS character escape sequences . 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 ~!@$%^&*()_+-=,./';:"?><[]\{}|`#, the selector would look like this:

CSS:

<style>
 #\~\!\@\$\%\^\&\*\(\)\_\+-\=,円\.\/\'\;\:\"\?\>\<\[\]\\\{\}\|\`\#
 {
 background: hotpink;
 }
</style>
<script>
 // document.getElementById or similar
 document.getElementById('~!@$%^&*()_+-=,./\';:"?><[]\\{}|`#');
 // document.querySelector or similar
 $('#\\~\\!\\@\\$\\%\\^\\&\\*\\(\\)\\_\\+-\\=\,円\\.\\/\\\'\\;\\:\\"\\?\\>\\<\\[\\]\\\\\\{\\}\\|\\`\\#');
</script>
answered Jul 6, 2011 at 6:41

2 Comments

Excellent answer. In the <style> selector, where does the \\\ between the escaped [] and {} come from? There doesn't seem to be a backslash in between [] and {} in the original ID. Edit: It may be stackoverflow's parser, which seems to be affecting my comment.
Doesn't really answer the spirit of the question, which I think would preclude any escaping gymnastics. Besides, this was more of a bug which has since been closed.
72

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

relevant paragraph:

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 "B26円 W3円F".

As @mipadi points out in Kenan Banks'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

answered Jan 15, 2009 at 23:45

Comments

28

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 characters, except "-" and "_" are not allowed if used directly. But you can encode them using a backslash foo\~bar or using the Unicode notation foo7円E bar.

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Jan 16, 2009 at 0:05

1 Comment

This incorrectly accepts a{ as in a{ { color: red; }.
18

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:

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

Sources:

  1. https://benfrain.com/when-and-where-you-can-use-numbers-in-id-and-class-names/
  2. Is there a workaround to make CSS classes with names that start with numbers valid?
  3. https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
Simon
1,5831 gold badge15 silver badges26 bronze badges
answered Jun 23, 2016 at 17:33

Comments

9

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 symbol, and even emoji works.

<style>
 .😭 {
 border: 2px solid blue;
 width: 100px;
 height: 100px;
 overflow: hidden;
 }
</style>
<div class="😭">
 😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅😅
</div>

Enter image description here

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Nov 14, 2021 at 13:37

Comments

6

We can use all characters in a class name. Even characters like # and .. We just have to escape them with \ (backslash).

.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>

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Aug 5, 2020 at 15:50

Comments

6

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

https://developer.mozilla.org/en/underscores_in_class_and_id_names

"...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.

answered Jul 31, 2010 at 5:33

Comments

5

For HTML5 and CSS 3, classes and IDs can start with numbers.

Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Oct 12, 2009 at 14:04

1 Comment

But css selectors still need to be escaped by unicode code point. Ex: css selector for class 10 needs to be .31円 0
-1

Going off of Kenan Banks's answer, you can use the following two regex matches to make a string valid:

[^a-z0-9A-Z_-]

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

^-*[0-9]+

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 two or more characters long
return 2 <= strlen($class) ? $class : '';
Peter Mortensen
31.5k22 gold badges110 silver badges134 bronze badges
answered Sep 7, 2019 at 14:42

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.