Usando querySelector com IDs que são números

94

Pelo que entendi, a especificação HTML5 permite que você use IDs que são números como este.

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

Posso acessá-los usando, getElementByIdmas não com querySelector. Se eu tentar fazer o seguinte, obtenho SyntaxError: DOM Exception 12 no console.

document.querySelector("#1")

Estou curioso para saber por que usar números como IDs não funciona querySelectorquando a especificação do HTML5 diz que eles são válidos. Tentei vários navegadores.

Berry Blue
fonte
1
Não acho que a especificação HTML5 diga que eles são válidos. Vou verificar ...
beautifulcoder
3
@beautifulcoder Eles são válidos
dsgriffin
1
Esqueça, de acordo com validator.w3.org/check é válido usar números. Talvez os navegadores modernos ainda não tenham implementado o padrão?
beautifulcoder

Respostas:

107

É válido, mas requer algum tratamento especial. A partir daqui: http://mathiasbynens.be/notes/css-escapes

Dígitos iniciais

Se o primeiro caractere de um identificador for numérico, você precisará escapar dele com base em seu ponto de código Unicode. Por exemplo, o ponto de código para o caractere 1 é U + 0031, então você deve escapar dele como \ 000031 ou \ 31.

Basicamente, para escapar de qualquer caractere numérico, basta prefixá-lo com \ 3 e adicionar um caractere de espaço (). Yay Unicode!

Portanto, seu código acabaria como (CSS primeiro, JS depois):

#\31  {
    background: hotpink;
}

document.getElementById('1');
document.querySelector('#\\31 ');
Dennis
fonte
Qual seria a sintaxe para valores maiores que 9? Não consigo fazer isso funcionar com IDs como 10.
Berry Blue
5
Você precisa de um espaço após o primeiro caractere: #\\31 0- você pode se referir a mothereffingcssescapes.com
Dennis
Obrigado pelo acompanhamento e pelo link!
Berry Blue
1
Observe que o espaço só é necessário se um caractere que é um dígito hexadecimal seguir imediatamente a seqüência de escape, a fim de distinguir esse caractere da seqüência de escape. Consulte w3.org/TR/CSS21/syndata.html#characters para obter mais detalhes.
BoltClock
83

Porque, embora sejam válidos na especificação HTML5, não são válidos em CSS, que é o que significa " seletor de consulta ".

Em vez disso, você teria que fazer isso document.querySelector("[id='1']"):, o que é muito prolixo, considerando que você poderia dar a ele um ID significativo como message1ou algo assim;)

Niet the Dark Absol
fonte
1
Você não "precisa" - existe uma maneira de usar um seletor de id com um dígito inicial. No entanto, concordo que é melhor ter um id significativo.
Dennis
9
UUIDs podem começar por um número.
Alfonso Nishikawa,
19

Eu precisava de uma abordagem automatizada. Uma mudança recente significa que os valores de id usados ​​não são mais caracteres alfabéticos simples e incluem números e caracteres especiais.

Acabei usando CSS.escape: https://developer.mozilla.org/en-US/docs/Web/API/CSS/escape

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

Primeiro, este é o caso de falha:

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

E agora usando CSS.escape:

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

Veja como muda corretamente para mostrar After, demonstrando que o seletor funcionou!

Glavin001
fonte
A partir de hoje, quando você precisar lidar com algum id estranho que você não controla, esta é a solução mais limpa, até porque é suportada por todos os navegadores modernos.
LasaleFamine
3

Da documentação do W3C Sintaxe dos seletores de atributos

Os valores dos atributos devem ser identificadores CSS ou String válidos.

Portanto, dígitos ou cadeias alfanuméricas com dígito inicial não se qualificam como identificadores válidos.

Se você estiver usando um utilitário gerador de ID para gerar um identificador, pode acabar com ids alfanuméricos com dígitos iniciais.

Uma solução rápida seria omitir dígitos do SEED do gerador (se ele puder ser modificado) ou sempre anexar uma string ao id gerado.

vikash Mishra
fonte
2

Aqui está uma função que fiz agora para lidar com IDs de números iniciais em seletores CSS, e é segura para o IE, o que não é CSS.escape.

Passe o seletor por esta função cleanSelector antes de usá-lo:

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 ); 

Por
fonte