Why can an element id not start with an integer? [duplicate]

Why can an element id not start with an integer?

They can. But a CSS ID selector cannot start with a digit. E.g., this HTML is valid:

<div id="1foo">testing 1 2 3</div>

…but this CSS is not valid:

#1foo {
    color: green;
}

The CSS standard says that an id selector cannot start with an unescaped digit:

An ID selector contains a “number sign” (U+0023, #) immediately followed by the ID value, which must be an CSS identifiers.

And then defining CSS identifier:

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

(My emphasis.)

So in theory, you can work around the #1foo not working by escaping the digit in the CSS selector. For instance:

HTML:

<div id="1foo">testing 1 2 3</div>

CSS:

#\31 foo {
    color: green;
}

…where 31 is the character code for "1" in hex. Live Example:

#\31 foo {
  color: green;
}
<div id="1foo">testing 1 2 3</div>

But the selector can’t literally start with a digit, and in general it’s such a hassle I would avoid bothering. I also can’t speak to how well the various things that need to interpret CSS selectors work when doing this. jQuery handles it correctly, FWIW. E.g.:

$("#\\31 foo").css("color", "blue");

…works. Live Example:

setTimeout(function() {
  $("#\\31 foo").css("color", "blue");
}, 2000);
#\31 foo {
  color: green;
}
<div id="1foo">testing 1 2 3, this should be green, and in two seconds it'll turn blue</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

(Note that you have to escape the backslash in the string, because backslashes are special in JavaScript strings, so to get an actual backslash in the selector, you need two in the string.)

As for why CSS would have this restriction (and why HTML used to, although browsers never enforced it), we can only speculate. Mr. Alien points out in the comments that most programming languages disallow starting identifiers with a digit. HTML and CSS are not, of course, programming languages, but the id values created via HTML are reflected as property names in DOM objects, which are accessed via programming languages. It may just be that the people doing the specs were following what they felt was convention or trying to provide some compatibility with programming languages. That’s speculation, though.

Leave a Comment