Selettore CSS “(A o B) e C”?


176

Questo dovrebbe essere semplice, ma sto riscontrando problemi nel trovare i termini di ricerca.
Diciamo che ho questo:

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

In CSS, come posso creare un selettore che corrisponda a qualcosa che corrisponde a "(.a o .b) e .c"?

So che potrei farlo:

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

Ma, supponendo che dovrò fare molto questo tipo di logica, con una varietà di combinazioni logiche, esiste una sintassi migliore?


Fai attenzione se devi supportare Internet Explorer 6, perché ignorerà più di un nome di classe in un selettore CSS.
fforw

24
Fortunatamente, per questo progetto, posso dire agli utenti di IE6 di aggiornarsi.
Josh,

12
Per motivi di chiarezza, cerco di inserire sempre una nuova riga dopo le virgole, o almeno uno spazio.
ANeves,

2
@ANeves +1 per la nuova linea. Questo è il miglior approccio secondo me, specialmente quando si usa il controllo del codice sorgente.
Curt,

Risposte:


149

c'è una sintassi migliore?

No. L' oroperatore CSS ( ,) non consente i raggruppamenti. È essenzialmente l'operatore logico con la precedenza più bassa nei selettori, quindi è necessario utilizzarlo .a.c,.b.c.


25

Non ancora, ma esiste la funzione sperimentale di :matches()pseudo-classe che fa proprio questo:

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

Puoi trovare maggiori informazioni qui e qui . Attualmente, la maggior parte dei browser supporta la sua versione iniziale :any(), che funziona allo stesso modo, ma sarà sostituita da :matches(). Non ci resta che attendere un po 'di più prima di usarlo ovunque (sicuramente lo farò).


È irragionevole incolpare IE per non aver implementato qualcosa a cui semplicemente non avevano mai pensato e che non era in nessuna bozza per cominciare. :-moz-any()e si :-webkit-any()presentò molto prima che Mozilla lo suggerisse per Selectors 4 (portando alla sua attuale incarnazione come :matches()).
BoltClock

1
È altrettanto irragionevole aspettarsi che qualsiasi fornitore attui una funzione da una bozza instabile indipendentemente da quanto tempo la bozza è stata resa disponibile (questo per spiegare il fatto che Selector 4 rimane instabile e in gran parte non implementato più di tre anni dopo il suo FPWD) .
BoltClock

@BoltClock, hanno incolpato IE6 per un intero decennio per cose che non esistevano nel 2001. Le persone vogliono solo incolpare qualcuno.
GetFree

Una parola su quelle sperimentali è che non vuoi iniziare a fare affidamento su di esse a meno che non sia implementato ufficialmente. Sebbene possa sembrare un'ottima soluzione, la possibilità che scompaia ciò che personalmente mi impedisce di implementarlo nei miei progetti. Anche tenere traccia di una pseudo classe sperimentale non mi fa sentire al sicuro. Molto probabilmente verrà utilizzato in più di un posto nel progetto e, nel caso, e se ne hai più di uno dove lo usi, devi in ​​qualche modo tenere traccia di tutto. Puoi sicuramente avere fallback e comunque
risolverlo

sono l'unico a cui viene visualizzato un Uncaught DOMException: Failed to execute 'querySelector' on 'Document': ':any(.a .b)' is not a valid selector.errore? 🤔
thomas,

12

Se hai questo:

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

E vuoi solo selezionare gli elementi che hanno .xe ( .ao .b), puoi scrivere:

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

ma è conveniente solo quando hai tre "sottoclassi" e vuoi selezionarne due.

Selezione di una sola sottoclasse (ad esempio .a):.a.x

Selezione di due sottoclassi (ad esempio .ae .b):.x:not(.c)

Selezione di tutte e tre le sottoclassi: .x


6
Qualsiasi clausola logica del modulo a or b or c or dè la stessa di not(not(a) and not(b) and not(c) and not(d))"o" è in realtà solo una funzione di convenienza. In teoria dovrebbe essere possibile cavarsela senza di essa in tutti i casi. Nel caso del PO (.a or .b) and .c->:not(:not(.a):not(.b)).c
Max Murphy,

2
@MaxMurphy Hai provato questo?
Šime Vidas

4
Stamattina alle cinque in punto, sì! Ho js che sputa la logica del primo ordine, con i selettori alle foglie, dando risultati come :not(:not([data-status="ACT"]):not([data-status="ISS"]):not([data-status="COR"]))[data-month="08"]. Il codice non è abbastanza pulito per la lettura pubblica, tuttavia, altrimenti lo pubblicherei. Ho provato su Chrome, Safari e un telefono Android di fascia bassa.
Max Murphy,

2
@MaxMurphy Hai un ottimo punto, ma penso che tu abbia invocato una definizione piuttosto torturata di "funzione di convenienza". Tutto ciò che un computer digitale può fare può essere scomposto in porte NAND, ma non definirei il resto dell'ingegneria del software "un mucchio di funzioni utili". Le differenze di grado diventano rapidamente differenze di fatto di tipo quando i costrutti possono essere combinati.
Sarah G,

1
@MaxMurphy Ho avuto delle difficoltà a capire che stavi solo scherzando. :( La pseudo-classe CSS di negazione,: not (X), è una notazione funzionale che prende come argomento un selettore X semplice . Corrisponde a un elemento non rappresentato dall'argomento. X non deve contenere un altro selettore di negazione . (Da Mozilla docs ,
accentation

5

No. I CSS standard non forniscono il tipo di cose che stai cercando.

Tuttavia, potresti voler esaminare LESS e SASS .

Questi sono due progetti che mirano a estendere la sintassi CSS predefinita introducendo funzionalità aggiuntive, tra cui variabili, regole nidificate e altri miglioramenti.

Ti consentono di scrivere un codice CSS molto più strutturato e uno dei due risolverà quasi sicuramente il tuo caso d'uso particolare.

Ovviamente, nessuno dei browser supporta la loro sintassi estesa (soprattutto perché i due progetti hanno sintassi e funzionalità diverse), ma ciò che fanno è fornire un "compilatore" che converte il tuo codice LESS o SASS in CSS standard, che puoi quindi distribuire sul tuo sito.


A quel punto, potrei anche usare la stampa PHP "Content-type: text / css"
Josh
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.