Corso di CSS / Ereditarietà, specificità e cascata CSS
La cascata sceglie tra dichiarazioni CSS in competizione, mentre la specificità confronta la forza dei selettori all'interno delle condizioni di cascata pertinenti. L'ereditarietà fornisce determinati valori da un genitore quando nessuna dichiarazione applicabile li determina; questi sono meccanismi correlati ma diversi.
Distingui l'ereditarietà dalle dichiarazioni dirette
L'ereditarietà si verifica quando un elemento figlio eredita il valore del suo elemento genitore. Mentre il colore del testo e le proprietà relative ai font vengono generalmente ereditati, bordi e padding non sono ereditati di default. Se si assume che tutte le proprietà siano uguali a quelle del genitore, si rischia di attendersi nei paragrafi bordi che in realtà non vengono ereditati.
#main {
color: purple;
border: 1px solid purple;
}
p { color: #555; }
<main id="main">
<h1>Small Garden</h1>
<p>Visitor information.</p>
</main>
Considerando soltanto questi due frammenti, h1 erediterà il colore viola dal suo genitore main. Il colore grigio che specifichi viene applicato a p. Solo perché il #main del genitore è un selettore ID, non significa che prevalga sull'assegnazione diretta del figlio p. Questo perché non si tratta di una competizione tra due selettori che si applicano allo stesso elemento. Il bordo viene creato attorno al box di main e non viene duplicato dai bordi di h1 e p rispettivamente.
Le proprietà non ereditate possono anche ereditare il valore calcolato del genitore specificandolo come border: inherit. Al contrario, anche se esiste una dichiarazione che si applica all'elemento, anche se si tratta di una proprietà ereditata, tale dichiarazione viene elaborata per prima. Puoi scoprire quali proprietà sono ereditate e cosa significa inherit nella descrizione dell'eredità CSS di MDN.
Segui il processo decisionale della cascata
Inizia con il CSS ordinario dell'autore, come le regole che scrivi per questa pagina. Prima di confrontare le dichiarazioni, verifica che il selettore corrisponda, che la sintassi sia valida e che le condizioni come le media query si applichino. Escludi le regole non corrispondenti e le dichiarazioni non valide dal confronto.
- Controlla prima origine, importanza e layer. Fonti CSS dell'autore, CSS dell'utente/stile predefinito del browser, se è !important, se viene utilizzato @layer, ecc. sono rilevanti qui. Se le condizioni principali sono diverse, la decisione non viene presa confrontando solo i punteggi dei selettori.
- Confronta la specificità dei selettori all'interno delle stesse condizioni. La priorità (specificità) è un criterio per confrontare quanto è specifico un selettore. Confronta ID, famiglia di classi e famiglia di elementi in quest'ordine.
- Se la priorità è la stessa, viene utilizzata la dichiarazione scritta successivamente. In situazioni in cui non ci sono condizioni aggiuntive come @scope, come negli esempi di questa lezione, i pareggi finali vengono risolti nell'ordine nel codice sorgente.
- Per ogni proprietà, il CSS risolve le dichiarazioni applicabili e poi esegue l'impostazione dei valori predefiniti dove necessario. Le proprietà ereditabili possono ottenere un valore dal genitore; altre proprietà normalmente usano il loro valore iniziale. Questo non significa che ogni dichiarazione in una regola vincente sostituisca un'intera regola precedente.
La cascata è l'intero processo di risoluzione dei conflitti CSS; la specificità dei selettori è un criterio al suo interno. Animazioni, transizioni, livelli e scope introducono ulteriori regole, quindi i semplici esempi qui riportati non rappresentano tutti i casi. Le regole di ordinamento della cascata W3C definiscono le relazioni tra origine, importanza e livelli. L'esempio completo qui sotto non utilizza animazioni, transizioni, @layer o @scope. La lezione Organizzare CSS con stili condivisi, nesting e layer dimostra come raggruppare le regole in livelli.
Confronta la specificità in tre colonne
Il selettore di base in questa lezione può essere letto in tre colonne: numero di ID, numero di classi/attributi/pseudo-classi e numero di elementi/pseudo-elementi. Confronta dalla colonna di sinistra e, se c'è una differenza, decidi in base al risultato. Non limitarti a memorizzarlo come una tabella di punteggio decimale aggiungendo semplicemente ID=100, classe=10, elemento=1. Solo perché ci sono molte classi non significa che superi la colonna ID.
| selettore | ID | Classe, attributo, pseudo-classe | Elemento/Pseudo-elemento | notazione |
|---|---|---|---|---|
p |
0 | 0 | 1 | 0-0-1 |
.notice |
0 | 1 | 0 | 0-1-0 |
p.notice |
0 | 1 | 1 | 0-1-1 |
[required] |
0 | 1 | 0 | 0-1-0 |
a:hover |
0 | 1 | 1 | 0-1-1 |
p::before |
0 | 0 | 2 | 0-0-2 |
#opening |
1 | 0 | 0 | 1-0-0 |
#main .notice |
1 | 1 | 0 | 1-1-0 |
p.notice e .notice hanno la stessa colonna ID e la stessa colonna classe. C'è una differenza tra 1 e 0 nella colonna elemento, quindi p.notice ha specificità maggiore. #opening e p.notice hanno una differenza di 1 e 0 nella prima colonna, quindi #opening ha specificità maggiore. Spazi bianchi, notazioni relazionali come >, +, ~ e il selettore universale * non aumentano direttamente il numero di questi confronti.
p.notice { color: #087f5b; }
.notice { color: tomato; }
Sotto le stesse condizioni di origine, importanza e livello, p.notice ha una specificità maggiore rispetto a .notice, quindi il suo colore verde prevale anche quando appare prima. I selettori identici hanno la stessa specificità, permettendo all'ordine nel codice sorgente di risolvere un pareggio. Alcune pseudo-classi funzionali hanno regole di specificità aggiuntive. Vedi MDN: Specificità.
Risolvi ciascuna proprietà separatamente
.notice {
color: blue;
padding: 12px;
border: 1px solid #087f5b;
}
.notice {
color: tomato;
padding: 20px;
}
Se solo queste due regole vengono applicate allo stesso elemento, colore e padding utilizzano la dichiarazione della seconda, mentre il bordo della regola precedente rimane. Solo perché nella regola successiva non c'è alcun bordo non significa che l'intera regola precedente scompaia. Il CSS dovrebbe essere inteso come “determinare valori per ciascuna proprietà” piuttosto che “selezionare un intero blocco di regole”.
Ad esempio, il colore del testo può derivare da una regola ID, il margine può derivare da una regola di classe successiva e il bordo può derivare da una regola di classe precedente. Anche quando vedi il testo barrato negli strumenti per sviluppatori, leggi le dichiarazioni una per una. Il fatto che il colore sia barrato non significa che il padding dello stesso blocco non sia applicato.
Prevedi l'esempio completo prima di eseguirlo
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Small Garden</title>
<style>
body { margin: 24px; font-family: sans-serif; line-height: 1.7; }
#main { color: purple; }
p { color: #555; }
.notice {
color: blue;
padding: 12px;
border: 1px solid #087f5b;
}
p.notice { color: #087f5b; }
.notice { color: tomato; padding: 20px; }
#opening { color: #1d4ed8; }
</style>
</head>
<body>
<main id="main">
<h1>Small Garden</h1>
<p id="opening" class="notice">A: We open at 9am every day.</p>
<p class="notice">B: Prepare a water bottle and comfortable shoes.</p>
<p>C: Please inquire at the information desk.</p>
</main>
</body>
</html>
Prevedi i colori di A·B·C e il padding dell’avviso prima di aprirlo nel tuo browser. Se salvi l'intero codice come index.html e lo apri, otterrai il seguente risultato. Il font del body e l'altezza della linea sono impostazioni ausiliarie per una più facile visualizzazione.
| oggetto e proprietà | risultato finale | Motivo della decisione |
|---|---|---|
| colore di h1 | Viola | Eredita il colore di main. Non ci sono altre dichiarazioni di colore in h1. |
| colore di A | Blu #1d4ed8 | #opening ha una specificità maggiore rispetto a p.notice, .notice, p applicati allo stesso A. |
| colore di B | Verde #087f5b | p.notice ha una specificità maggiore rispetto alla regola .notice scritta successivamente. |
| colore di C | Grigio #555 | Usa un valore diretto per p e non eredita il colore viola del genitore. |
| padding di A·B | 20px | Le due dichiarazioni .notice hanno la stessa specificità, quindi prevale il padding della seconda. |
| bordo di A·B | linea continua verde di 1px | Poiché non c'è alcuna dichiarazione di bordo nella seconda regola, la dichiarazione valida precedente rimane. |
Quando controllato in Computed, il colore di A può essere visualizzato come rgb(29, 78, 216), il colore di B può essere visualizzato come rgb(8, 127, 91) e il colore di C può essere visualizzato come rgb(85, 85, 85). Anche se la notazione del colore è diversa, indica lo stesso valore. Controllare che il padding sia di 20px in ogni direzione e che lo spessore del bordo e la forma della linea siano gli stessi.
Confronta gli stili !important e inline
!important è una notazione che cambia l'importanza di una dichiarazione. Non è una funzione che aggiunge un numero grande alle tre colonne del selettore. Dalla stessa fonte dell'autore, le dichiarazioni importanti hanno la precedenza sulle dichiarazioni normali, quindi aggiungere la regola qui sotto alla fine dell'intero esempio cambierà il colore sia di A che di B nel colore CSS tomato. La dichiarazione del colore semplice in ID non ha nemmeno la precedenza su questa dichiarazione importante.
.notice { color: tomato !important; }
Questo risultato non significa che important sia sempre più forte di tutti gli stili. Gli stili important dell'utente, i valori durante le transizioni, ecc. seguono un ordine separato. Anche tra le dichiarazioni important, devi prima controllare la sorgente e il livello. In questo esercizio, osserva important e poi elimina la regola che hai aggiunto. Di solito, per la manutenzione è meglio organizzare prima l'intervallo di selezione e la struttura.
<p class="notice" style="color: purple;">B: Information on what to prepare</p>
Nell'esempio originale in cui la regola important è stata eliminata, se metti un colore inline in B come sopra, esso avrà la precedenza sulle regole del foglio di stile normale e B diventerà viola. Gli stili inline sono trattati separatamente dalle tre colonne dei selettori predefiniti nella tabella sopra. Ancora una volta, inserire important nella regola della classe generale permette ad essa di avere la precedenza sul normale colore inline. Pertanto, “se è inline, è incondizionatamente il più forte” è anche una spiegazione senza condizioni.
Esercitati a diagnosticare i conflitti
- Nell'esempio completo originale, sposta la regola
p.noticein fondo. Assicurati che B sia ancora verde e che A mantenga il colore blu del suo ID. Negli stati con alta specificità, essi non saranno semplicemente sovrascritti cambiando il loro ordine. - Successivamente, cambia solo il selettore p.notice in
.noticee posizionalo in basso. Il colore di B utilizza il verde specificato dall'ultima .notice. Poiché abbiamo lo stesso selettore, l'ordine è ora il criterio decisionale. Dopo la conferma, ripristina l'originale. - Rimuovi solo
id="opening"da A. Controlla se A diventa dello stesso verde di B. Anche se l'ID del genitore main rimane lo stesso, non supera il colore verde assegnato direttamente ad A. Dopo la conferma, il tuo ID sarà ripristinato. - In passaggi separati, applica gli esempi con !important e con stili inline sopra uno per uno e confrontali. Invece di lasciare indietro le regole pratiche precedenti, torna all'originale e aggiungi le seguenti condizioni:
Se il risultato differisce dalle tue aspettative, Esaminare CSS con DevTools: Styles e Computed. Seleziona l'elemento corretto, trova le dichiarazioni per la proprietà, confronta la loro importanza, i selettori e l'ordine, e poi controlla il valore finale. Aggiungere ID o !important senza trovare la causa potrebbe cambiare il colore ora rendendo più difficili modifiche successive.




