Which Characters Are Valid in CSS Class Names/Selectors

Which characters are valid in CSS class names/selectors?

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

Allowed characters for CSS identifiers

The charset doesn't matter. The allowed characters matters more. Check the CSS specification. Here's a cite of relevance:

In CSS, identifiers (including element names, classes, and IDs in selectors) can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, 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".

Update: As to the regex question, you can find the grammar here:

ident      -?{nmstart}{nmchar}*

Which contains of the parts:

nmstart    [_a-z]|{nonascii}|{escape}
nmchar [_a-z0-9-]|{nonascii}|{escape}
nonascii [\240-\377]
escape {unicode}|\\[^\r\n\f0-9a-f]
unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])?
h [0-9a-f]

This can be translated to a Java regex as follows (I only added parentheses to parts containing the OR and escaped the backslashes):

String h = "[0-9a-f]";
String unicode = "\\\\{h}{1,6}(\\r\\n|[ \\t\\r\\n\\f])?".replace("{h}", h);
String escape = "({unicode}|\\\\[^\\r\\n\\f0-9a-f])".replace("{unicode}", unicode);
String nonascii = "[\\240-\\377]";
String nmchar = "([_a-z0-9-]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String nmstart = "([_a-z]|{nonascii}|{escape})".replace("{nonascii}", nonascii).replace("{escape}", escape);
String ident = "-?{nmstart}{nmchar}*".replace("{nmstart}", nmstart).replace("{nmchar}", nmchar);

System.out.println(ident); // The full regex.

Update 2: oh, you're more a PHP'er, well I think you can figure how/where to do str_replace?

What characters are widely supported in CSS class names?

Note that class names are defined by HTML, not CSS. HTML4 says the class attribute is a cdata-list, which is space-separated tokens. So a single classname token can contain any character except the whitespace characters.

I wonder what browsers properly understands a slash (/) in a class name, and what browsers support class names starting with a number.

To refer to such names in a CSS class selector you would need to use an escape. eg.:

<div class="1blah/bläh">

is matched by:

.\31 blah\2F bläh { ... }

This is supported by all current browsers. It wasn't supported by IE5, but that's thankfully no longer a concern. (If you had concerns about character encoding mismatches, you might prefer to encode the ä as \E4, but that's not a limitation of CSS as such.)

If you're asking which browsers will let you get away with the invalid selector

.1blah/bläh

Then, well, who cares really? Just use the valid one.

Is there a workaround to make CSS classes with names that start with numbers valid?

There are no CSS classes. The question logically splits to two questions: can you start a class name with a digit in HTML, and (assuming the answer is “yes”, as it is) if it does, how do you use the corresponding class selector in CSS?

Various HTML specifications impose various restrictions on class names, but in browser practice, and according to HTML5, there are no limitations, except that a class name cannot contain whitespace characters. So class=000000-8 is valid.

By CSS syntax rules, a CSS identifier cannot being with an unescaped digit. Therefore, a selector like .000000-8 is invalid. But the digit can be escaped, by CSS escaping rules: the selector

.\30 00000-8

or, equivalently,

.\00003000000-8 

is valid and matches an element with class=000000-8.

Needless to say, class names starting with a digit are best avoided, but if you have to work with them (e.g., because some HTML documents have them and you cannot change the markup), this is the way.

Special characters in CSS selectors

In CSS, identifiers (including element
names, classes, and IDs in selectors)
can contain only the characters
[a-zA-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).code (see next item).

http://www.w3.org/TR/CSS21/syndata.html#characters

Can I use Chinese characters in CSS class names?

Yes, you can use Chinese characters as class names and selectors.

div {  width: 100px;  height: 100px;}
.tomato { background: tomato;}
.蓝色 { background: navy;}
<div class="蓝色"></div><div class="tomato"></div><br><button onclick="console.log(document.querySelector('.蓝色'))">Find Element</button>

CSS classes with special characters

Is this class even valid?

It depends on what you're validating against.

profile[~redString] is a valid HTML class name, exemplified by putting the markup through a validator.

However, .profile[~redString] is not a valid CSS selector, because the ~ is a special symbol as you have found out, and it's not in a place where the CSS parser would expect it. When you escape it, you get

.profile[\~redString]

which is a valid selector, but with a completely different meaning. It represents an element with a class name profile, as well as an attribute called ~redString. It does not represent an element with a class name that is exactly profile[~redString].

To match this element, you need to escape the square brackets as well. This will result in the entire stream of characters being treated as a single identifier:

.profile\[\~redString\]

Alternatively, you can use an attribute selector instead to make things cleaner:

[class~="profile[~redString]"]

Notice the ~= in this CSS2.1 attribute selector, which works similarly to a class selector.

See both selectors in action:

:first-child.profile\[\~redString\],:last-child[class~="profile[~redString]"] {  color: red;}
<div>  <div class="profileElement profile[~redString]">123</div>  <div class="profileElement profile[~redString]">456</div></div>

Is it possible to use the space character in CSS class names?

https://html.spec.whatwg.org/multipage/dom.html#classes

When specified on HTML elements, the class attribute must have a value that is a set of space-separated tokens representing the various classes that the element belongs to.

Of course it’s possible to escape a space character, e.g. — HTML attribute values can contain character references per https://html.spec.whatwg.org/multipage/syntax.html#syntax-attribute-value:

Attribute values are a mixture of text and character references, except with the additional restriction that the text cannot contain an ambiguous ampersand.

However, it doesn’t matter whether the space is HTML-escaped or not for the above statement to apply. A HTML-encoded space character still decodes to a space character, and so e.g. class="a b" still results in “a set of space-separated tokens”. See e.g. https://html.spec.whatwg.org/multipage/parsing.html#attribute-value-(double-quoted)-state for how double-quoted attribute values are parsed.



Related Topics



Leave a reply



Submit