Sélecteur CSS «(A ou B) et C»?

176

Cela devrait être simple, mais j'ai du mal à trouver les termes de recherche.
Disons que j'ai ceci:

<div class="a c">Foo</div>
<div class="b c">Bar</div>

En CSS, comment puis-je créer un sélecteur qui correspond à quelque chose qui correspond à "(.a ou .b) et .c"?

Je sais que je pourrais faire ceci:

.a.c,.b.c {
  /* CSS stuff */
}

Mais, en supposant que je vais devoir faire beaucoup ce genre de logique, avec une variété de combinaisons logiques, y a-t-il une meilleure syntaxe?

Josh
la source
Soyez prudent si vous devez prendre en charge Internet Explorer 6, car il ignorera simplement plus d'un nom de classe dans un sélecteur CSS.
pour le
24
Heureusement, pour ce projet, je peux dire aux utilisateurs d'IE6 de se mettre à niveau eux-mêmes.
Josh
12
Par souci de clarté, j'essaie de toujours mettre une nouvelle ligne après les virgules, ou à tout le moins un espace.
ANeves le
2
@ANeves +1 pour la nouvelle ligne. C'est la meilleure approche à mon avis, en particulier lors de l'utilisation du contrôle de source.
Curt

Réponses:

149

y a-t-il une meilleure syntaxe?

L' oropérateur CSS ( ,) n'autorise pas les regroupements. Il s'agit essentiellement de l'opérateur logique de priorité la plus basse dans les sélecteurs, vous devez donc l'utiliser .a.c,.b.c.

Matt Ball
la source
25

Pas encore, mais il y a la :matches()fonction de pseudo-classe expérimentale qui fait exactement cela:

:matches(.a .b) .c {
  /* stuff goes here */
}

Vous pouvez trouver plus d'informations à ce sujet ici et ici . Actuellement, la plupart des navigateurs prennent en charge sa version initiale :any(), qui fonctionne de la même manière, mais sera remplacée par :matches(). Nous devons juste attendre un peu plus avant de l'utiliser partout (je le ferai sûrement).

Metalcoder
la source
Il est déraisonnable de blâmer IE de ne pas avoir mis en œuvre quelque chose auquel ils n'avaient tout simplement jamais pensé et qui ne figurait dans aucun projet au départ. :-moz-any()et est :-webkit-any()apparu bien avant que Mozilla ne le suggère pour Selectors 4 (menant à son incarnation actuelle comme :matches()).
BoltClock
1
Il est tout aussi déraisonnable de s'attendre à ce qu'un fournisseur implémente une fonctionnalité à partir d'un brouillon instable, quelle que soit la durée de la mise à disposition du brouillon (cela tient compte du fait que Selectors 4 reste instable et en grande partie non implémenté plus de trois ans après son FPWD) .
BoltClock
@BoltClock, ils ont blâmé IE6 pendant une décennie entière pour des choses qui n'existaient pas en 2001. Les gens veulent juste blâmer quelqu'un.
GetFree
Un mot sur les expérimentaux est que vous ne voulez pas commencer à vous en remettre à moins qu'ils ne soient officiellement mis en œuvre. Bien que cela puisse sembler une excellente solution - la possibilité qu'elle disparaisse ce qui m'empêche personnellement de la mettre en œuvre dans mes projets. Même garder une trace d'une pseudo classe expérimentale ne me fait pas me sentir en sécurité. Très probablement, il sera utilisé à plus d'un endroit dans le projet et au cas où et si vous en avez plusieurs où vous l'utilisez, vous devez en quelque sorte garder une trace de tout cela. Vous pouvez sûrement avoir des
solutions de rechange
suis-je le seul à avoir une Uncaught DOMException: Failed to execute 'querySelector' on 'Document': ':any(.a .b)' is not a valid selector.erreur? 🤔
thomas
12

Si vous avez ceci:

<div class="a x">Foo</div>
<div class="b x">Bar</div>
<div class="c x">Baz</div>

Et vous ne voulez sélectionner que les éléments qui ont .xet ( .aou .b), vous pouvez écrire:

.x:not(.c) { ... }

mais ce n'est pratique que lorsque vous avez trois "sous-classes" et que vous voulez en sélectionner deux.

Sélection d'une seule sous-classe (par exemple .a):.a.x

Sélection de deux sous-classes (par exemple .aet .b):.x:not(.c)

Sélection des trois sous-classes: .x

Šime Vidas
la source
6
Toute clause logique du formulaire a or b or c or dest la même que not(not(a) and not(b) and not(c) and not(d))so 'ou' n'est en fait qu'une fonction de commodité. En théorie, il devrait être possible de s'en passer dans tous les cas. Dans le cas de l'OP (.a or .b) and .c->:not(:not(.a):not(.b)).c
Max Murphy
2
@MaxMurphy Avez-vous testé cela?
Šime Vidas
4
A cinq heures ce matin, oui! J'ai js qui crache la logique du premier ordre, avec des sélecteurs aux feuilles, donnant des résultats tels que :not(:not([data-status="ACT"]):not([data-status="ISS"]):not([data-status="COR"]))[data-month="08"]. Le code n'est pas assez propre pour une lecture publique, sinon je le posterais. J'ai testé sur chrome, safari et un téléphone Android bas de gamme.
Max Murphy
2
@MaxMurphy Vous avez un excellent point, mais je pense que vous avez invoqué une définition assez torturée de «fonction de commodité». Tout ce qu'un ordinateur numérique peut faire peut être décomposé en portes NAND, mais je n'appellerais pas le reste du génie logiciel «un tas de fonctions pratiques». Les différences de degré deviennent rapidement des différences de facto de nature lorsque les constructions peuvent être combinées.
Sarah G
1
@MaxMurphy J'ai eu du mal à comprendre que vous plaisantiez. :( La pseudo-classe CSS de négation,: not (X), est une notation fonctionnelle prenant un simple sélecteur X comme argument. Elle correspond à un élément qui n'est pas représenté par l'argument. X ne doit pas contenir un autre sélecteur de négation . (De Mozilla docs , emphase mine)
törzsmókus
5

Non. Le CSS standard ne fournit pas le genre de chose que vous recherchez.

Cependant, vous voudrez peut-être vous pencher sur LESS et SASS .

Ce sont deux projets qui visent à étendre la syntaxe CSS par défaut en introduisant des fonctionnalités supplémentaires, notamment des variables, des règles imbriquées et d'autres améliorations.

Ils vous permettent d'écrire du code CSS beaucoup plus structuré, et l'un ou l'autre résoudra presque certainement votre cas d'utilisation particulier.

Bien sûr, aucun des navigateurs ne prend en charge sa syntaxe étendue (d'autant plus que les deux projets ont chacun une syntaxe et des fonctionnalités différentes), mais ils fournissent un "compilateur" qui convertit votre code LESS ou SASS en CSS standard, que vous pouvez ensuite déployer sur votre site.

Spudley
la source
À ce stade, je pourrais aussi bien utiliser l'impression PHP "Content-type: text / css"
Josh