Perché questo filtro CSS: not () non scende?

Voglio selezionare gli span che non sono i discendenti di una class specifica, chiamiamolo “no”. Ecco il mio CSS:

div:not(.no) span{background-color:#00f;} 

Ecco l’HTML

 
yes 1
no 1
no 2

Due domande:

  1. Perché il mio CSS si applica sia a yes 1 che a no 2?
  2. Perché l’intera cosa si rompe se passo a un selettore universale?

     *:not(.no) span{background-color:#00f;} 

Ecco il codice in JSFiddle: http://jsfiddle.net/stephaniehobson/JtNZm/

    1. Entrambi gli elementi padre div elementi span non hanno il numero di class, indipendentemente dal fatto che altri antenati lo abbiano o no:

       
      yes 1
       
      no 2
    2. Sia html che body , che sono gli antenati degli elementi div e span , soddisfano *:not(.no) quando si utilizza un selettore universale (o piuttosto, quando si omette un selettore di tipi). Questo fa sì che tutti gli elementi di span abbiano il colore di sfondo.

    Una soluzione a questo è di ancorare il tuo filtro di negazione all’elemento del body usando il combinatore di bambini, se i tuoi elementi div livello superiore saranno sempre figli del body :

     body > div:not(.no) span { background-color: #00f; } 

    demo di jsFiddle

    Un’altra soluzione è semplicemente usare gli stili di override.

    BoltClock è corretto. Potrebbe avere più senso se si pronuncia il selettore in questo modo:

    Seleziona un elemento span
    che discende da un elemento div
    il cui valore di class non contiene la parola no .

    Ciascuno degli span selezionati nel tuo esempio è in realtà discendente da un div cui valore di class non contiene la parola no – il fatto che il secondo di essi è anche discendente da un div cui valore di class contiene la parola no no negare (ha!) la dichiarazione precedente.

    Ciò che è interessante è che scommetterei che se avessi spostato il secondo no scendere di un livello, la seconda span sarebbe ancora abbinata. Il CSS non ha una nozione di prossimità degli elementi, quindi qualsiasi div antenati dovrebbe essere sufficiente per far corrispondere il selettore, indipendentemente dal fatto che sia “più vicino” allo span o meno.

    Penso che la scelta migliore sia dividere la tua affermazione in 2:

     div span { background-color:#00f; } .no span { background-color:#fff; } 

    Puoi vedere l’effetto qui: http://jsfiddle.net/JHTqp/