Quels caractères sont valides dans les noms / sélecteurs de classe CSS?

1203

Quels caractères / symboles sont autorisés dans les sélecteurs de classe CSS ?
Je sais que les caractères suivants ne sont pas valides , mais quels caractères sont valides ?

~ ! @ $ % ^ & * ( ) + = , . / ' ; : " ? > < [ ] \ { } | ` #
Darryl Hein
la source
5
Question connexe: stackoverflow.com/questions/2812072/…
BalusC
32
qu'en est-il des caractères utf8? Comme je peux taper en grec
GorillaApe
9
Les caractères spéciaux peuvent être utilisés dans les noms de classe en les échapper - dans votre fichier CSS , vous pouvez définir une .hello/worldclasse en échappant à la barre oblique inverse: .hello\2fworld, hello\2f worldouhello\/world
wyqydsyq
1
Une autre question connexe, non pas sur la "syntaxe des noms", mais sur la "syntaxe de l'attribut de classe" lors de l' expression de plusieurs noms .
Peter Krauss
2
Vous pouvez également utiliser des emoji. npmjs.com/package/postcss-modules-emoji-classname
Kevin Suttle

Réponses:

1024

Vous pouvez vérifier directement à la grammaire CSS .

Fondamentalement 1 , un nom doit commencer par un trait de soulignement ( _), un trait d'union ( -) ou une lettre ( a- z), suivi d'un nombre quelconque de tirets, traits de soulignement, lettres ou chiffres. Il y a un hic: si le premier caractère est un trait d'union, le deuxième caractère doit 2 être une lettre ou un trait de soulignement, et le nom doit comporter au moins 2 caractères.

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

En bref, la règle précédente se traduit par ce qui suit, extrait de la spécification W3C. :

En CSS, les identificateurs (y compris les noms d'élément, les classes et les ID dans les sélecteurs) ne peuvent contenir que les caractères [a-z0-9] et ISO 10646 U + 00A1 et supérieurs, plus le trait d'union (-) et le trait de soulignement (_) ; ils ne peuvent pas commencer par un chiffre ou un tiret suivi d'un chiffre. Les identificateurs peuvent également contenir des caractères d'échappement et tout caractère ISO 10646 sous forme de code numérique (voir l'élément suivant). Par exemple, l'identifiant "B&W?" peut s'écrire "B \ & W \?" ou "B \ 26 W \ 3F".

Les identifiants commençant par un trait d'union ou un trait de soulignement sont généralement réservés aux extensions spécifiques au navigateur, comme dans -moz-opacity.

1 Tout est rendu un peu plus compliqué par l'inclusion de caractères unicode échappés (que personne n'utilise vraiment).

2 Notez que, selon la grammaire que j'ai liée, une règle commençant par DEUX traits d'union, par exemple --indent1, n'est pas valide. Cependant, je suis presque sûr d'avoir vu cela en pratique.

Triptyque
la source
57
NB: Le W3C indique que l'utilisation d'un début «-» ou «_» doit être réservée aux extensions CSS spécifiques au fournisseur (par exemple, les classes -moz * implémentées par les navigateurs Mozilla).
mipadi
3
Les \ -escapes sont couramment utilisés, mais généralement principalement à des fins de piratage CSS, isolant les navigateurs qui ne les prennent pas en charge.
bobince le
5
Pour mettre à jour le commentaire de @Pim Jager plus de deux ans plus tard, selon w3counter.com/globalstats.php, IE6 est désormais utilisé par moins de 3% des utilisateurs, derrière IE9 sur 4%, IE7 sur 9%, IE8 sur 22%. Toutes les versions de Firefox ont 28%, toutes les versions de Chrome ont 17%.
Daniel Earwicker
3
Je sais que c'est une vieille réponse, mais CSS (au moins 2+) autorise tout caractère {non-ASCII} dans les identificateurs.
user2864740
11
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". Donc - --indent1n'est pas valide et doit être échappé comme \--indent1(les --classes
s'arrêtent
177

À ma grande surprise, la plupart des réponses ici sont fausses. Il se trouve que:

Tout caractère sauf NUL est autorisé dans les noms de classe CSS en CSS. (Si CSS contient NUL (échappé ou non), le résultat n'est pas défini. [ CSS-caractères ])

La réponse de Mathias Bynens contient des liens vers des explications et des démos montrant comment utiliser ces noms.Écrit dans le code CSS, un nom de classe peut nécessiter un échappement , mais cela ne change pas le nom de la classe. Par exemple, une représentation inutilement trop échappée sera différente des autres représentations de ce nom, mais elle fait toujours référence au même nom de classe.

La plupart des autres langages (de programmation) n'ont pas ce concept d'échappement des noms de variables («identificateurs»), donc toutes les représentations d'une variable doivent avoir la même apparence. Ce n'est pas le cas en CSS.

Notez qu'en HTML, il n'y a aucun moyen d'inclure des caractères d'espace (espace, tabulation, saut de ligne, saut de page et retour chariot) dans un attribut de nom de classe , car ils séparent déjà les classes les unes des autres.

Donc, si vous devez transformer une chaîne aléatoire en un nom de classe CSS: prenez soin de NUL et de l'espace, et échappez (en conséquence pour CSS ou HTML). Terminé.

Robert Siemer
la source
7
La première ligne de votre réponse doit être «la plupart des réponses ici sont obsolètes / s'appliquent uniquement à CSS2».
Salman A
7
@SalmanA Les réponses auxquelles je fais référence étaient erronées depuis le début. Ils ne s'appliquent ni à CSS2.1, CSS2 ni CSS1.
Robert Siemer
@RobertSiemer bon point, j'ai déplacé mon commentaire sur stackoverflow.com/questions/50812118/… (ce qui n'est jamais le moins lié à ce sujet)
Peter T.
Et implémentation JavaScript: github.com/mathiasbynens/CSS.escape/blob/master/css.escape.js
Duarte Cunha Leão
71

J'ai répondu à votre question en profondeur ici: http://mathiasbynens.be/notes/css-escapes

L'article explique également comment échapper n'importe quel caractère en CSS (et JavaScript), et j'ai également créé un outil pratique pour cela. Depuis cette page:

Si vous deviez donner à un élément une valeur d'ID de ~!@$%^&*()_+-=,./';:"?><[]{}|`#, le sélecteur ressemblerait à ceci:

CSS:

<style>
  #\~\!\@\$\%\^\&\*\(\)\_\+-\=\,\.\/\'\;\:\"\?\>\<\[\]\\\{\}\|\`\#
  {
    background: hotpink;
  }
</style>

JavaScript:

<script>
  // document.getElementById or similar
  document.getElementById('~!@$%^&*()_+-=,./\';:"?><[]\\{}|`#');
  // document.querySelector or similar
  $('#\\~\\!\\@\\$\\%\\^\\&\\*\\(\\)\\_\\+-\\=\\,\\.\\/\\\'\\;\\:\\"\\?\\>\\<\\[\\]\\\\\\{\\}\\|\\`\\#');
</script>
Mathias Bynens
la source
4
@ Darryl Bien sûr, c'est un exemple assez extrême, mais des trucs comme ça class="404-error"peuvent être utiles.
Mathias Bynens
j'ai un exemple: je convertis une syntaxe mettant en évidence la sortie du système en CSS. il a des noms de classe comme «ISO C ++: Types ( _t / _type)». si je ne remplace que les espaces, j'ai des noms de classe valides.
moutons volants
Sur votre site Web, vous dites que le caractère espace peut être échappé. Quand je l'essaye dans un nom de classe, je n'arrive pas à le faire fonctionner. Je remarque qu'il n'y a pas d'espace dans cet exemple. C'est possible?
Adamarla
@Adamarla <p class="foo bar">ajoute deux classes à l' pélément :, fooet bar. Il n'y a aucun moyen (auquel je peux penser) d'ajouter un nom de classe contenant des espaces à un élément HTML. Les informations sur la façon d'échapper les caractères d'espacement ont été incluses car il est utile d'échapper ces caractères dans d'autres contextes d'identification, par exemple les noms de famille de polices.
Mathias Bynens
3
Comme pour la plupart des choses de la vie, il semble en CSS qu'il y ait une différence entre "techniquement légal à l'extrême" et "sain".
Volksman
69

Lire la spécification W3C . (c'est CSS 2.1, trouvez la version appropriée pour votre hypothèse de navigateurs)

modifier: le paragraphe pertinent suit:

En CSS, les identificateurs (y compris les noms d'élément, les classes et les ID dans les sélecteurs) ne peuvent contenir que les caractères [a-z0-9] et ISO 10646 U + 00A1 et supérieurs, plus le trait d'union (-) et le trait de soulignement (_) ; ils ne peuvent pas commencer par un chiffre ou un tiret suivi d'un chiffre. Les identificateurs peuvent également contenir des caractères d'échappement et tout caractère ISO 10646 sous forme de code numérique (voir l'élément suivant). Par exemple, l'identifiant "B&W?" peut s'écrire "B \ & W \?" ou "B \ 26 W \ 3F".

edit 2: comme le souligne @mipadi dans la réponse de Triptych, il y a cette mise en garde , également sur la même page Web:

En CSS, les identifiants peuvent commencer par «-» (tiret) ou «_» (trait de soulignement). Les mots clés et les noms de propriété commençant par «-» ou «_» sont réservés aux extensions spécifiques au fournisseur. Ces extensions spécifiques au fournisseur doivent avoir l'un des formats suivants:

'-' + vendor identifier + '-' + meaningful name 
'_' + vendor identifier + '-' + meaningful name

Exemples):

Par exemple, si l'organisation XYZ a ajouté une propriété pour décrire la couleur de la bordure du côté est de l'écran, elle pourrait l'appeler -xyz-border-east-color.

Autres exemples connus:

 -moz-box-sizing
 -moz-border-radius
 -wap-accesskey

Un tiret initial ou un trait de soulignement est garanti de ne jamais être utilisé dans une propriété ou un mot clé par n'importe quel niveau actuel ou futur de CSS. Ainsi, les implémentations CSS typiques peuvent ne pas reconnaître ces propriétés et peuvent les ignorer conformément aux règles de gestion des erreurs d'analyse. Cependant, comme le tiret ou le trait de soulignement initial fait partie de la grammaire, les implémenteurs CSS 2.1 devraient toujours être en mesure d'utiliser un analyseur conforme à CSS, qu'ils prennent en charge ou non des extensions spécifiques au fournisseur.

Les auteurs doivent éviter les extensions spécifiques au fournisseur

Jason S
la source
Je faisais référence à votre deuxième édition sur les tirets et les traits de soulignement, mais j'ai oublié de clarifier cela. Désolé pour la confusion.
Albin
24

L'expression régulière complète est:

-?(?:[_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])*

Ainsi, tous vos personnages répertoriés, à l'exception de " -" et " _", ne sont pas autorisés s'ils sont utilisés directement. Mais vous pouvez les encoder en utilisant une barre oblique inverse foo\~barou en utilisant la notation unicode foo\7E bar.

Gombo
la source
pourquoi [\200-\377]? [\178-\1114112]est autorisé sans échappatoire en CSS 3.
moutons volants
\377ici est en fait mal. Il y a une note sur la grammaire de la section Lexical Scanner de CSS2.1 qui stipule: "Le" \ 377 "représente le plus grand nombre de caractères que les versions actuelles de Flex peuvent traiter (décimal 255). Il doit être lu comme" \ 4177777 "( décimal 1114111), qui est le point de code le plus élevé possible dans Unicode / ISO-10646. " Cela devrait également être le \240cas non \377. Je suppose que cela fait maintenant 7 ans, donc les choses ont probablement changé un peu depuis lors.
James Donnelly
1
Je pense qu'une expression régulière plus précise serait -?(?:[_a-z]|(?![\u0000-\u0239]).*|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])(?:[_a-z0-9-]|(?![\u0000-\u0239]).*|\\[0-9a-f]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-f])*.
James Donnelly
2
@JamesDonnelly N'hésitez pas à modifier ma réponse si vous pensez qu'elle a besoin d'une mise à jour.
Gumbo
11

Pour ceux qui recherchent une solution de contournement, vous pouvez utiliser un sélecteur d'attribut, par exemple, si votre classe commence par un nombre. Changement:

.000000-8{background:url(../../images/common/000000-0.8.png);} /* DOESN'T WORK!! */

pour ça:

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

De plus, s'il y a plusieurs classes, vous devrez les spécifier dans le sélecteur je pense.

Sources:

  1. https://benfrain.com/when-and-where-you-can-use-numbers-in-id-and-class-names/
  2. Existe-t-il une solution de contournement pour rendre valides les classes CSS dont les noms commencent par des nombres?
D.Tate
la source
5

Je crois comprendre que le soulignement est techniquement valable. Check-out:

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

"... les errata des spécifications publiées début 2001 ont rendu les soulignements légaux pour la première fois."

L'article lié ci-dessus dit de ne jamais les utiliser, puis donne une liste des navigateurs qui ne les prennent pas en charge, qui sont tous, en termes de nombre d'utilisateurs au moins, redondants depuis longtemps.

mofaha
la source
4

Pour les classes et les ID HTML5 / CSS3 peuvent commencer par des nombres.

Marius
la source
1
Avez-vous une source pour cela? Peut-être que je manque quelque chose, mais les spécificateurs CSS3 spécifient des liens vers la définition des identifiants dans la spécification CSS 2.1 qui ne permet pas les nombres principaux.
Ryan
11
w3.org/TR/2003/WD-css3-syntax-20030813/#characters <- ne permet toujours pas les premiers chiffres, etc. (même si cela fonctionne)
Jamie Pate
10
HTML 5 permet aux classes et aux ID de commencer par un nombre (par exemple class="1a"). Cependant, un identifiant CSS ne peut pas commencer par un nombre (par exemple .1a, ne fonctionnera pas). Vous pouvez y échapper, difficile (par exemple .\31 aou .\000031a).
Oriol
Bien que cela fonctionne normalement en CSS, mais il semble que ce ne soit toujours pas officiel. "Les noms de propriété et les noms de règle sont toujours des identificateurs, qui doivent commencer par une lettre ou un trait d'union suivi d'une lettre, et peuvent ensuite contenir des lettres, des chiffres, des tirets ou des traits de soulignement." - w3.org/TR/css3-syntax/#syntax-description
Autocollants
@Pangloss Mais les noms de classe ne sont pas des noms de propriété ou des noms de règles.
Bennett McElwee du
1

En partant de la réponse de @ Triptych, vous pouvez utiliser les 2 correspondances d'expression régulière suivantes pour rendre une chaîne valide:

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

Il s'agit d'une correspondance inverse qui sélectionne tout ce qui n'est pas une lettre, un chiffre, un tiret ou un trait de soulignement pour un retrait facile.

^-*[0-9]+

Cela correspond à 0 ou 1 tirets suivi d'un ou plusieurs chiffres au début d'une chaîne, également pour une suppression facile.

Comment je l'utilise en 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 2 or more characters long
return 2 <= strlen($class) ? $class : '';
Manny Fleurmond
la source