Using querySelector with IDs that are numbers

From what I understand the HTML5 spec lets you use IDs that are numbers like this.

<div id="1"></div>
<div id="2"></div>

I can access these fine using getElementById but not with querySelector. If I try do the following I get SyntaxError: DOM Exception 12 in the console.

document.querySelector("#1")

I’m just curious why using numbers as IDs does not work querySelector when the HTML5 spec says these are valid. I tried multiple browsers.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

It is valid, but requires some special handling. From here: http://mathiasbynens.be/notes/css-escapes

Leading digits

If the first character of an identifier is numeric, you’ll need to escape it based on its Unicode code point. For example, the code point for the character 1 is U+0031, so you would escape it as 00031 or 31 .

Basically, to escape any numeric character, just prefix it with 3 and append a space character ( ). Yay Unicode!

So your code would end up as (CSS first, JS second):

#31  {
    background: hotpink;
}

document.getElementById('1');
document.querySelector('#\31 ');

Method 2

Because while they are valid in the HTML5 spec, they are not valid in CSS, which is what “query selector” means.

Instead, you would have to do this: document.querySelector("[id='1']"), which is very long-winded considering you could give it a meaningful ID like message1 or something 😉

Method 3

I needed an approach which was automated. A recent change meant the id values used were no longer simple alphabetic characters and included numbers and special characters.

I ended up using CSS.escape: https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape

console.log(CSS.escape('1'));

First, this is the failing case:

const theId = "1";
document.querySelector(`#${theId}`);
const el = document.querySelector(`#${theId}`);
el.innerHTML = "After";
<div id="1">Before</div>

And now using CSS.escape:

const theId = "1";
const el = document.querySelector(`#${CSS.escape(theId)}`);
el.innerHTML = "After";
<div id="1">Before</div>

See how it correctly changes to show After, demonstrating the selector worked!

Method 4

Here is a function I made just now for dealing with leading number ID’s in CSS selectors, and it is IE safe as CSS.escape is not.

Pass the selector through this cleanSelector function before using it :

var cleanSelector = function(selector){
    (selector.match(/(#[0-9][^s:,]*)/g) || []).forEach(function(n){
        selector = selector.replace(n, '[id="' + n.replace("#", "") + '"]');
    });
    return selector;
};

var myselector = ".dog #980sada_as div span#aside:hover div.apple#05crab:nth-of-type(2), .ginger #2_green_div, div.cupcake #darwin p#23434-346365-53453";

var clean_myselector = cleanSelector(myselector);

// print to show difference
console.log(myselector);
console.log(clean_myselector);

//use the new selector like normal
var elems = document.querySelectorAll( clean_myselector );

Method 5

From the W3C documentation Attribute selectors syntax

Attribute values must be a valid CSS identifiers or String.

Thus, digits or alphanumeric strings with leading digit does not qualify as a valid identifier.

If you are using an ID generator utility for generating an identifier, you might end up with alpha numeric ids with leading digits.

A quick fix would be to either omit digits from the SEED of the generator( if it can be modified ) or always append a string to the id generated.

Method 6

To use dynamic Ids in the query selector have used simple code.

this.template.querySelector("[id='"+divId+"']");

If you are working on the iterations and want to access on id then checkout this code.
I had iteration on accounts object and using clickable event on LWC:

<template for:each={accounts.data} for:item="acc">
     <div key={acc.Id} id={acc.Id} class="box" onclick={handleClick}>
       {acc.Name}
     </div>
</template>

I wanted to access div data with using its ID when calling the onclick event on the div.

handleClick(event){
 event.dataTransfer.setData("divId", event.target.id);
 var divId = event.dataTransfer.getData("divId");

 //Using the divId in querySelector       
 var Element = this.template.querySelector("[id='"+divId+"']");

}


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x