Existe-t-il un sélecteur CSS par préfixe de classe?

182

Je souhaite appliquer une règle CSS à tout élément dont l'une des classes correspond au préfixe spécifié.

Par exemple, je veux une règle qui s'appliquera à div dont la classe commence par status-(A et C, mais pas B dans l'extrait suivant):

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

Une sorte de combinaison de:
div[class|=status]etdiv[class~=status-]

Est-ce faisable sous CSS 2.1? Est-ce faisable avec n'importe quelle spécification CSS?

Remarque: je sais que je peux utiliser jQuery pour émuler cela.

THX-1138
la source

Réponses:

388

Ce n'est pas faisable avec CSS2.1, mais c'est possible avec les sélecteurs de correspondance de sous-chaînes d'attributs CSS3 (qui sont pris en charge dans IE7 +):

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

Notez le caractère espace dans le deuxième sélecteur d'attribut. Cela récupère les divéléments dont l' classattribut remplit l'une de ces conditions:

  • [class^="status-"] - commence par "status-"

  • [class*=" status-"]- contient la sous-chaîne "status-" apparaissant directement après un caractère espace. Les noms de classe sont séparés par des espaces conformément aux spécifications HTML , d'où le caractère d'espace significatif. Cela vérifie toutes les autres classes après la première si plusieurs classes sont spécifiées, et ajoute un bonus de vérification de la première classe au cas où la valeur d'attribut serait remplie d'espace (ce qui peut arriver avec certaines applications qui produisent des classattributs de manière dynamique).

Naturellement, cela fonctionne également dans jQuery, comme démontré ici .

La raison pour laquelle vous devez combiner deux sélecteurs d'attribut comme décrit ci-dessus est qu'un sélecteur d'attribut tel que [class*="status-"]correspondra à l'élément suivant, ce qui peut être indésirable:

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

Si vous pouvez vous assurer qu'un tel scénario ne se produira jamais , vous êtes libre d'utiliser un tel sélecteur pour des raisons de simplicité. Cependant, la combinaison ci-dessus est beaucoup plus robuste.

Si vous avez le contrôle sur la source HTML ou l'application générant le balisage, il peut être plus simple de créer simplement le status-préfixe dans sa propre statusclasse, comme le suggère Gumbo .

BoltClock
la source
1
Si pour une raison étrange vous avez une classe appelée status-et que vous ne voulez pas correspondre à cela, le sélecteur devient encore plus compliqué: de div[class^="status-"]:not(.status-), div[class*=" status-"]:not(.status-)plus, vous perdez le support IE7 / IE8. Heureusement, si votre balisage est sain d'esprit, vous n'aurez pas besoin d'exclure une telle classe.
BoltClock
Quel est le problème avec ceci: [class*=" anim-overlay-"] a:hover:after{...}. Mes classes CSS sont anim-overlay-1, anim-overlay-2.....anim-overlay-8
MB Parvez Rony
2
@WebDevRon: Vous avez oublié la partie ^ =. Si votre attribut de classe est garanti pour commencer par anim-overlay, alors vous n'avez probablement pas besoin de la partie * =.
BoltClock
Merci. Une autre chose, puis-je l'utiliser .anim-overlay-*{...}?
MB Parvez Rony
2
@Daniel Compton: Merci pour la modification. J'ai été mis au courant avec le recul de la façon dont des mots comme ça peuvent être condescendants pour quelqu'un pour qui quelque chose n'est peut-être pas si évident. Je sais que certaines personnes n'apprécient vraiment pas ce genre de changement, alors je réponds principalement pour vous faire savoir que je l'apprécie.
BoltClock
14

Les sélecteurs d'attributs CSS vous permettront de vérifier les attributs d'une chaîne. (dans ce cas - un nom de classe)

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

(on dirait qu'il est en fait au statut de `` recommandation '' pour 2.1 et 3)


Voici un aperçu de la façon dont je * pense que cela fonctionne:

  • [ ]: est le conteneur pour les sélecteurs complexes si vous voulez ...
  • class: 'class' est l' attribut que vous regardez dans ce cas.
  • * : modificateur (le cas échéant): dans ce cas - "wildcard" indique que vous recherchez N'IMPORTE QUELLE correspondance.
  • test- : la valeur (en supposant qu'il y en a un) de l'attribut - qui contient la chaîne "test-" (qui pourrait être n'importe quoi)

Ainsi, par exemple:

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

Vous pourriez être plus précis si vous avez une bonne raison, avec l'élément aussi

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

J'ai essayé de trouver des cas extrêmes, mais je ne vois pas la nécessité d'utiliser une combinaison de ^et *- car * obtient tout ...

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

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

Tout ce qui est au-dessus d'IE6 obéira avec plaisir. :)

Notez que:

[class] { ... }

Sélectionne n'importe quoi avec une classe ...

shérifderek
la source
[class*='test-']correspondra à des éléments tels que <div class='foo-test-bar'>. C'est le cas unique qui nécessite de combiner ^ et * comme décrit dans ma réponse. Et IE6 ne prend pas en charge les sélecteurs d'attributs.
BoltClock
@BoltClock - merci de clarifier! - Je ne supporte pas <EI9 - et je n'écrirais jamais de classes qui marcheraient les unes sur les autres - donc pour moi cela fonctionne. :)
sheriffderek
6

Cela n'est pas possible avec les sélecteurs CSS. Mais vous pouvez utiliser deux classes au lieu d'une, par exemple status et important au lieu de status-important .

Gombo
la source
14
Bonne idée de séparer dans sa propre classe, mais il est possible avec des sélecteurs CSS. Voyez ma réponse.
BoltClock
2

Vous ne pouvez pas faire ça non. Il y a un sélecteur d'attribut qui correspond exactement ou partiellement jusqu'au signe -, mais cela ne fonctionnera pas ici car vous avez plusieurs attributs. Si le nom de classe que vous recherchez est toujours le premier, vous pouvez le faire:

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

Notez que ceci est juste pour indiquer quel sélecteur d'attribut CSS est le plus proche, il n'est pas recommandé de supposer que les noms de classe seront toujours devant car javascript pourrait manipuler l'attribut.

SBUJOLD
la source
2
ouais, j'y ai pensé. Cela peut devenir un problème lorsque jQuery entre en image, car il peut insérer une classe à l'avant.
THX-1138 du
Oui, je vais modifier mon message pour qu'il soit clair que ce n'est clairement pas une façon recommandée de le faire. Si vous avez le contrôle sur les noms de classe, la suggestion de Gumbo serait certainement la voie à suivre (et les sélecteurs d'attributs sur les anciens navigateurs IE ne sont pas pris en charge).
SBUJOLD