¿Qué caracteres son válidos en los nombres / selectores de clase CSS?

1203

¿Qué caracteres / símbolos están permitidos dentro de los selectores de clase CSS ?
Sé que los siguientes caracteres no son válidos , pero ¿qué caracteres son válidos ?

~ ! @ $ % ^ & * ( ) + = , . / ' ; : " ? > < [ ] \ { } | ` #
Darryl Hein
fuente
55
Pregunta relacionada: stackoverflow.com/questions/2812072/…
BalusC
32
¿Qué pasa con los caracteres utf8? Como puedo escribir en griego
GorillaApe
99
Los caracteres especiales se pueden utilizar en los nombres de clase por escapar de ellos - en su archivo CSS se puede definir una .hello/worldclase por escapar de la barra invertida: .hello\2fworld, hello\2f worldohello\/world
wyqydsyq
1
Otra pregunta relacionada, no sobre "sintaxis de nombres", sino sobre "sintaxis de atributo de clase" cuando se expresan varios nombres .
Peter Krauss
2
También puedes usar emoji. npmjs.com/package/postcss-modules-emoji-classname
Kevin Suttle

Respuestas:

1024

Puede consultar directamente en la gramática CSS .

Básicamente 1 , un nombre debe comenzar con un guión bajo ( _), un guión ( -) o una letra ( a- z), seguido de cualquier número de guiones, guiones bajos, letras o números. Hay una trampa: si el primer carácter es un guión, el segundo personaje debe 2 sea una letra o un guión bajo, y el nombre debe tener al menos 2 caracteres.

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

En resumen, la regla anterior se traduce a la siguiente, extraída de la especificación W3C. :

En CSS, los identificadores (incluidos los nombres de elementos, clases e ID en los selectores) pueden contener solo los caracteres [a-z0-9] y los caracteres ISO 10646 U + 00A1 y superiores, más el guión (-) y el guión bajo (_) ; no pueden comenzar con un dígito o un guión seguido de un dígito. Los identificadores también pueden contener caracteres escapados y cualquier carácter ISO 10646 como código numérico (consulte el siguiente elemento). Por ejemplo, el identificador "B & W?" puede escribirse como "B \ & W \?" o "B \ 26 W \ 3F".

Los identificadores que comienzan con un guión o un guión bajo generalmente están reservados para extensiones específicas del navegador, como en -moz-opacity.

1 Todo se vuelve un poco más complicado por la inclusión de caracteres Unicode escapados (que nadie usa realmente).

2 Tenga en cuenta que, según la gramática que vinculé, una regla que comienza con DOS guiones, por ejemplo --indent1, no es válida. Sin embargo, estoy bastante seguro de haber visto esto en la práctica.

Tríptico
fuente
57
NB: El W3C dice que el uso de un '-' o '_' principal debe reservarse para extensiones CSS específicas del proveedor (por ejemplo, clases -moz * implementadas por los navegadores Mozilla).
mipadi
3
Los \ -escapes se usan comúnmente, pero generalmente para propósitos de hacks CSS, aislando navegadores que no los admiten.
bobince
55
Para actualizar el comentario de @Pim Jager más de dos años después, de acuerdo con w3counter.com/globalstats.php, IE6 ahora es utilizado por menos del 3% de los usuarios, detrás de IE9 en el 4%, IE7 en el 9%, IE8 en el 22%. Todas las versiones de Firefox tienen 28%, todas las versiones de Chrome tienen 17%.
Daniel Earwicker
3
Sé que esta es una respuesta anterior, pero CSS (al menos 2+) permite cualquier carácter {No ASCII} en los identificadores.
usuario2864740
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". Por lo tanto, --indent1no es válido y debe escaparse como \--indent1(las --clases se rompen en iOS, por ejemplo)
canceló el
177

Para mi sorpresa, la mayoría de las respuestas aquí son incorrectas. Resulta que:

Cualquier carácter, excepto NUL, está permitido en los nombres de clase CSS en CSS. (Si CSS contiene NUL (escapado o no), el resultado no está definido. [ CSS-caracteres ])

La respuesta de Mathias Bynens enlaza con explicaciones y demostraciones que muestran cómo usar estos nombres. Escrito en código CSS, un nombre de clase puede necesitar escapar , pero eso no cambia el nombre de la clase. Por ejemplo, una representación innecesariamente escapada se verá diferente de otras representaciones de ese nombre, pero aún se refiere al mismo nombre de clase.

La mayoría de los otros lenguajes (de programación) no tienen ese concepto de nombres de variables de escape ("identificadores"), por lo que todas las representaciones de una variable deben tener el mismo aspecto. Este no es el caso en CSS.

Tenga en cuenta que en HTML no hay forma de incluir caracteres de espacio (espacio, tabulación, avance de línea, avance de formulario y retorno de carro) en un atributo de nombre de clase , porque ya separan las clases entre sí.

Entonces, si necesita convertir una cadena aleatoria en un nombre de clase CSS: cuide NUL y espacio, y escape (en consecuencia para CSS o HTML). Hecho.

Robert Siemer
fuente
77
La primera línea de su respuesta debería ser "la mayoría de las respuestas aquí están desactualizadas / se aplican solo a CSS2".
Salman A
77
@SalmanA Las respuestas a las que me refiero fueron incorrectas desde el principio. No se aplican a CSS2.1, CSS2 ni CSS1.
Robert Siemer
@RobertSiemer buen punto, moví mi comentario a stackoverflow.com/questions/50812118/… (que nunca está menos relacionado con este tema)
Peter T.
Y la implementación de JavaScript: github.com/mathiasbynens/CSS.escape/blob/master/css.escape.js
Duarte Cunha Leão
71

He respondido su pregunta en profundidad aquí: http://mathiasbynens.be/notes/css-escapes

El artículo también explica cómo escapar de cualquier carácter en CSS (y JavaScript), y también hice una herramienta útil para esto. De esa página:

Si le diera a un elemento un valor de ID ~!@$%^&*()_+-=,./';:"?><[]{}|`#, el selector se vería así:

CSS:

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

JavaScript:

<script>
  // document.getElementById or similar
  document.getElementById('~!@$%^&*()_+-=,./\';:"?><[]\\{}|`#');
  // document.querySelector or similar
  $('#\\~\\!\\@\\$\\%\\^\\&\\*\\(\\)\\_\\+-\\=\\,\\.\\/\\\'\\;\\:\\"\\?\\>\\<\\[\\]\\\\\\{\\}\\|\\`\\#');
</script>
Mathias Bynens
fuente
44
@ Darryl Por supuesto, este es un ejemplo bastante extremo, pero cosas como class="404-error"pueden ser útiles.
Mathias Bynens
Tengo un ejemplo: convierto la salida de un sistema de resaltado de sintaxis a CSS. tiene nombres de clase como "ISO C ++: Tipos ( _t / _type)". si solo reemplazo espacios en blanco, tengo nombres de clase válidos.
ovejas voladoras
En su sitio web, usted dice que el carácter de espacio puede ser una barra invertida escapado. Cuando lo intento con un nombre de clase, no puedo hacer que funcione. Noté que no hay espacio en este ejemplo. ¿Es posible?
Adamarla
@Adamarla <p class="foo bar">agrega dos clases al pelemento: fooy bar. No hay forma (que se me ocurra) de agregar un nombre de clase que contenga espacios en blanco a un elemento HTML. La información sobre cómo escapar de los espacios en blanco se incluyó porque es útil para escapar de dichos caracteres en otros contextos identificadores, por ejemplo, nombres de familias de fuentes.
Mathias Bynens
3
Como con la mayoría de las cosas en la vida, en CSS parece que hay una diferencia entre "técnicamente legal hasta el extremo" y "sano".
Volksman
69

Lea la especificación W3C . (este es CSS 2.1, encuentre la versión adecuada para su suposición de navegadores)

editar: sigue el párrafo relevante:

En CSS, los identificadores (incluidos los nombres de elementos, clases e ID en los selectores) pueden contener solo los caracteres [a-z0-9] y los caracteres ISO 10646 U + 00A1 y superiores, más el guión (-) y el guión bajo (_) ; no pueden comenzar con un dígito o un guión seguido de un dígito. Los identificadores también pueden contener caracteres escapados y cualquier carácter ISO 10646 como código numérico (consulte el siguiente elemento). Por ejemplo, el identificador "B & W?" puede escribirse como "B \ & W \?" o "B \ 26 W \ 3F".

edición 2: como @mipadi señala en la respuesta de Triptych, existe esta advertencia , también en la misma página web:

En CSS, los identificadores pueden comenzar con '-' (guión) o '_' (guión bajo). Las palabras clave y los nombres de propiedad que comienzan con '-' o '_' están reservados para extensiones específicas del proveedor. Dichas extensiones específicas del proveedor deben tener uno de los siguientes formatos:

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

Ejemplo (s):

Por ejemplo, si la organización XYZ agrega una propiedad para describir el color del borde en el lado este de la pantalla, podría llamarlo -xyz-border-east-color.

Otros ejemplos conocidos:

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

Se garantiza que un guión inicial o guión bajo nunca se utilizará en una propiedad o palabra clave por ningún nivel actual o futuro de CSS. Por lo tanto, las implementaciones de CSS típicas pueden no reconocer tales propiedades y pueden ignorarlas de acuerdo con las reglas para manejar los errores de análisis. Sin embargo, debido a que el guión inicial o el guión bajo es parte de la gramática, los implementadores de CSS 2.1 siempre deberían poder usar un analizador compatible con CSS, independientemente de que admitan o no extensiones específicas del proveedor.

Los autores deben evitar extensiones específicas del proveedor

Jason S
fuente
Me refería a su segunda edición sobre guiones y guiones bajos, pero olvidé aclarar eso. Perdón por la confusion.
Albin
24

La expresión regular completa es:

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

Por lo tanto, todos los caracteres enumerados, excepto " -" y " _", no están permitidos si se usan directamente. Pero puede codificarlos con una barra diagonal inversa foo\~baro con la notación unicode foo\7E bar.

Gumbo
fuente
¿Por qué [\200-\377]? [\178-\1114112]está permitido sin escapes en CSS 3.
ovejas voladoras
\377Aquí está realmente mal. Hay una nota en la Gramática de la sección del Escáner Léxico de CSS2.1 que dice: "El" \ 377 "representa el número de caracteres más alto que las versiones actuales de Flex pueden manejar (decimal 255). Debe leerse como" \ 4177777 "( decimal 1114111), que es el punto de código más alto posible en Unicode / ISO-10646 ". También debería ser de \240también, no \377. Sin embargo, supongo que ahora tiene 7 años, por lo que las cosas probablemente han cambiado un poco desde entonces.
James Donnelly
1
Creo que sería una expresión regular más precisa -?(?:[_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 No dude en editar mi respuesta si cree que necesita alguna actualización.
Gumbo
11

Para aquellos que buscan una solución alternativa, puede usar un selector de atributos, por ejemplo, si su clase comienza con un número. Cambio:

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

a esto:

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

Además, si hay varias clases, creo que deberá especificarlas en el selector.

Fuentes:

  1. https://benfrain.com/when-and-where-you-can-use-numbers-in-id-and-class-names/
  2. ¿Hay alguna solución para hacer que las clases CSS con nombres que comienzan con números sean válidas?
D.Tate
fuente
5

Tengo entendido que el guión bajo es técnicamente válido. Revisa:

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

"... erratas a la especificación publicada a principios de 2001 hizo que los subrayados fueran legales por primera vez".

El artículo vinculado anteriormente dice que nunca los use, luego proporciona una lista de navegadores que no los admiten, todos los cuales son, en términos de números de usuarios al menos, redundantes durante mucho tiempo.

mofaha
fuente
4

Para HTML5 / CSS3, las clases y los ID pueden comenzar con números.

Mario
fuente
1
¿Tienes una fuente para esto? Tal vez me falta algo, pero la especificación de los selectores CSS3 enlaza con la definición de identificadores en la especificación CSS 2.1 que no permite números iniciales.
Ryan
11
w3.org/TR/2003/WD-css3-syntax-20030813/#characters <- todavía no permite números iniciales, etc. (aunque funciona)
Jamie Pate
10
HTML 5 permite que las clases y las ID comiencen con un número (por ejemplo class="1a"). Sin embargo, un identificador CSS no puede comenzar con un número (por ejemplo .1a, no funcionará). Puedes escapar de él, duro (por ejemplo, .\31 ao .\000031a).
Oriol
Aunque normalmente también funciona en CSS, parece que todavía no es oficial. "Los nombres de propiedad y los nombres de regla son siempre identificadores, que deben comenzar con una letra o un guión seguido de una letra, y luego pueden contener letras, números, guiones o guiones bajos". - w3.org/TR/css3-syntax/#syntax-description
Stickers
@Pangloss Pero los nombres de clase no son nombres de propiedad o nombres de reglas.
Bennett McElwee
1

A partir de la respuesta de @ Triptych, puede usar las siguientes 2 coincidencias de expresiones regulares para que una cadena sea válida:

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

Esta es una coincidencia inversa que selecciona cualquier cosa que no sea una letra, número, guión o guión bajo para facilitar su eliminación.

^-*[0-9]+

Esto coincide con 0 o 1 guiones seguidos de 1 o más números al comienzo de una cadena, también para una fácil eliminación.

Cómo lo uso 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
fuente