¿Hay un selector CSS por prefijo de clase?

175

Quiero aplicar una regla CSS a cualquier elemento cuya clase coincida con el prefijo especificado.

Por ejemplo, quiero una regla que se aplique a div que tiene una clase que comienza con status-(A y C, pero no B en el siguiente fragmento):

<div id='A' class='foo-class status-important bar-class'></div>
<div id='B' class='foo-class bar-class'></div>
<div id='C' class='foo-class status-low-priority bar-class'></div>

Algún tipo de combinación de:
div[class|=status]ydiv[class~=status-]

¿Es factible en CSS 2.1? ¿Es factible bajo alguna especificación CSS?

Nota: Sé que puedo usar jQuery para emular eso.

THX-1138
fuente

Respuestas:

373

No es factible con CSS2.1, pero es posible con los selectores de coincidencia de subcadenas de atributos CSS3 (que son compatibles con IE7 +):

div[class^="status-"], div[class*=" status-"]

Observe el carácter de espacio en el segundo selector de atributos. Esto recoge divelementos cuyo classatributo cumple cualquiera de estas condiciones:

  • [class^="status-"] - comienza con "estado-"

  • [class*=" status-"]- contiene la subcadena "status-" que ocurre directamente después de un carácter de espacio. Los nombres de clase están separados por espacios en blanco según la especificación HTML , de ahí el carácter de espacio significativo. Esto verifica cualquier otra clase después de la primera si se especifican varias clases, y agrega una ventaja de verificar la primera clase en caso de que el valor del atributo esté rellenado con espacio (lo que puede suceder con algunas aplicaciones que generan classatributos dinámicamente).

Naturalmente, esto también funciona en jQuery, como se demuestra aquí .

La razón por la que necesita combinar dos selectores de atributos como se describió anteriormente es porque un selector de atributos tal como [class*="status-"]coincidirá con el siguiente elemento, lo que puede ser indeseable:

<div id='D' class='foo-class foo-status-bar bar-class'></div>

Si puede asegurarse de que tal escenario nunca sucederá, entonces es libre de usar dicho selector por simplicidad. Sin embargo, la combinación anterior es mucho más robusta.

Si tiene control sobre la fuente HTML o la aplicación que genera el marcado, puede ser más simple simplemente hacer que el status-prefijo sea su propia statusclase, como sugiere Gumbo .

BoltClock
fuente
1
Si por alguna extraña razón tienes una clase llamada status-y no quieres igualarla, el selector se vuelve aún más complicado: div[class^="status-"]:not(.status-), div[class*=" status-"]:not(.status-)además, pierdes la compatibilidad con IE7 / IE8. Afortunadamente, si su marcado es correcto, no necesitará excluir dicha clase.
BoltClock
¿Qué está mal con esto: [class*=" anim-overlay-"] a:hover:after{...}. Mis clases de CSS son anim-overlay-1, anim-overlay-2.....anim-overlay-8
MB Parvez Rony
2
@WebDevRon: Olvidó la parte ^ =. Si se garantiza que su atributo de clase comenzará con anim-overlay, entonces probablemente no necesite la parte * =.
BoltClock
Gracias. Otra cosa, ¿puedo usar esto .anim-overlay-*{...}?
MB Parvez Rony
2
@Daniel Compton: Gracias por la edición. Me he dado cuenta en retrospectiva de cómo palabras como esa pueden ser condescendientes con alguien para quien algo podría no ser tan obvio. Sé que algunas personas realmente no aprecian este tipo de cambio, así que estoy respondiendo principalmente para hacerle saber que sí.
BoltClock
14

Los selectores de atributos CSS le permitirán verificar los atributos de una cadena. (en este caso, un nombre de clase)

https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors

(Parece que en realidad está en el estado de 'recomendación' para 2.1 y 3)


Aquí hay un resumen de cómo * creo que funciona:

  • [ ]: es el contenedor para selectores complejos si lo desea ...
  • class: 'clase' es el atributo que está viendo en este caso.
  • * : modificador (si lo hay): en este caso, "comodín" indica que está buscando CUALQUIER coincidencia.
  • test- : el valor (suponiendo que haya uno) del atributo, que contiene la cadena "test-" (que podría ser cualquier cosa)

Así por ejemplo:

[class*='test-'] {
  color: red;
}

Podría ser más específico si tiene una buena razón, con el elemento también

ul[class*='test-'] > li { ... }

He tratado de encontrar casos extremos, pero no veo la necesidad de usar una combinación de ^y *, como * obtiene todo ...

ejemplo: http://codepen.io/sheriffderek/pen/MaaBwp

http://caniuse.com/#feat=css-sel2

Todo lo que esté por encima de IE6 obedecerá felizmente. :)

tenga en cuenta que:

[class] { ... }

Seleccionará cualquier cosa con una clase ...

Sheriffderek
fuente
[class*='test-']coincidirá con elementos como <div class='foo-test-bar'>. Ese es el caso de un borde que requiere combinar ^ y * como se describe en mi respuesta. E IE6 no admite selectores de atributos.
BoltClock
@BoltClock: ¡gracias por aclarar! - No apoyo <EI9 - y nunca escribiría ninguna clase que se interpusiera - así que para mí esto funciona. :)
sheriffderek
6

Esto no es posible con los selectores CSS. Pero podría usar dos clases en lugar de una, por ejemplo, estado e importante en lugar de estado importante .

Gumbo
fuente
14
Buena idea sobre separarlo en su propia clase, pero es posible con selectores CSS. Mira mi respuesta.
BoltClock
2

No puedes hacer esto no. Hay un selector de atributos que coincide exactamente o parcialmente hasta un signo -, pero no funcionaría aquí porque tiene múltiples atributos. Si el nombre de la clase que está buscando siempre es el primero, puede hacer esto:

<html>
<head>
<title>Test Page</title>
<style type="text/css">
div[class|=status] { background-color:red; }
</style>
</head>
<body>
<div id='A' class='status-important bar-class'>A</div>
<div id='B' class='bar-class'>B</div>
<div id='C' class='status-low-priority bar-class'>C</div>

</body>
</html>

Tenga en cuenta que esto es solo para señalar qué selector de atributo CSS es el más cercano, no se recomienda asumir que los nombres de clase siempre estarán al frente ya que JavaScript podría manipular el atributo.

SBUJOLD
fuente
2
Sí, pensé en eso. Puede convertirse en un problema cuando jQuery entra en escena, ya que puede insertar una clase en el frente.
THX-1138
Sí, editaré mi publicación para que quede claro que claramente no es una forma recomendada de hacerlo. Si tiene control sobre los nombres de clase, entonces la sugerencia de Gumbo definitivamente sería el camino a seguir (más los selectores de atributos en navegadores IE más antiguos no son compatibles).
SBUJOLD