Cosa fa z-index
Quando gli elementi si sovrappongono, z-index decide quale viene disegnato davanti. Vince il numero più alto. Funziona sugli elementi posizionati (qualsiasi position tranne static) e sugli elementi flex e grid:
Senza z-index, gli elementi che vengono dopo nell'HTML sono disegnati sopra quelli precedenti, quindi C coprirebbe B e B coprirebbe A. I valori di z-index invertono questo ordine: A sta davanti, poi C, poi B.
I valori
| Valore | Significato |
|---|---|
auto (predefinito) | Impilato al livello 0 con i suoi fratelli, e non crea uno stacking context |
0 | Livello 0, ma crea uno stacking context |
| Intero positivo | Davanti ai valori più bassi |
| Intero negativo | Dietro il livello 0, e dietro il contenuto del genitore se è il genitore a formare lo stacking context |
Sono validi solo i numeri interi: z-index: 1.5 viene ignorato.
Perché uno z-index di 9999 può perdere: gli stacking context
I valori di z-index non vengono confrontati su tutta la pagina. Gli elementi sono raggruppati in stacking context, e uno z-index ordina solo gli elementi all'interno dello stesso contesto. Il contesto viene poi posizionato come un unico livello, usando lo z-index dell'elemento che l'ha creato.
Qui sotto, il menu a tendina blu ha z-index: 9999, ma vive dentro un header con z-index: 1. Il banner verde, fratello di quell'header, ha z-index: 2. L'intero livello dell'header, menu incluso, sta sotto il banner:
Premi il pulsante. Con z-index: auto l'header non forma più uno stacking context, quindi il 9999 del menu viene confrontato direttamente con il 2 del banner, e il menu passa in primo piano. Alzare il menu a 99999 non sarebbe mai servito.
Cosa crea uno stacking context
Una qualsiasi di queste proprietà trasforma un elemento in un proprio stacking context, intrappolando lo z-index di tutto ciò che contiene:
| Proprietà | Condizione |
|---|---|
position: relative o absolute | Con uno z-index diverso da auto |
position: fixed o sticky | Sempre |
| Elemento flex o grid | Con uno z-index diverso da auto |
opacity | Minore di 1 |
transform, scale, rotate, translate | Qualsiasi valore diverso da none |
filter, backdrop-filter | Qualsiasi valore diverso da none |
isolation | isolate |
mix-blend-mode | Qualsiasi valore diverso da normal |
will-change | Se nomina una delle proprietà qui sopra |
contain | layout o paint (e strict, content) |
Quelle che sorprendono sono opacity e transform: aggiungere una dissolvenza o un'animazione al passaggio del mouse su un genitore può mandare all'improvviso il suo menu a tendina dietro la sezione successiva.
Lo z-index: 10 del tooltip dovrebbe metterlo sopra la colonna successiva. Ma opacity: 0.99 fa della prima colonna uno stacking context con z-index auto (livello 0), e la seconda colonna viene dopo nell'HTML allo stesso livello, quindi viene disegnata sopra l'intera prima colonna, tooltip incluso. Cancella la riga di opacity e il tooltip torna davanti.
z-index negativo
Uno z-index negativo mette un elemento dietro i suoi fratelli. Se il genitore non forma uno stacking context, può finire persino dietro lo sfondo del genitore, una sorpresa frequente. isolation: isolate sul genitore crea un contesto senza nessun altro effetto visivo e tiene al suo interno il figlio negativo:
Senza isolation, la cornice ambra scivola dietro lo sfondo grigio del pulsante stesso, quindi se ne vede solo il bordo. Con isolation: isolate, la cornice resta dentro lo stacking context del pulsante: sopra il suo sfondo, sotto il suo testo.
Una scala di z-index
Scegli pochi livelli con un nome per tutto il sito invece di alzare i numeri all'infinito:
:root {
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 30;
--z-modal: 40;
--z-toast: 50;
}
.modal { position: fixed; z-index: var(--z-modal); }
La maggior parte dei bug di sovrapposizione sono bug di stacking context, non di numeri, quindi una piccola scala più isolation: isolate sui componenti che usano z-index al loro interno risolve molto. z-index ha bisogno del posizionamento per funzionare; la pagina su position lo spiega.
Errori comuni
- z-index su un elemento static. Aggiungi
position: relative(o rendilo un elemento flex o grid). - Salire fino a 9999. Se un genitore forma uno stacking context sotto il rivale, nessun valore del figlio può vincere. Cerca invece il contesto.
- Un nuovo
opacity,transformofiltersu un genitore che all'improvviso intrappola il suo menu a tendina. - Valori decimali.
z-index: 1.5non è valido. - Aspettarsi che
z-index: 0eautosi comportino allo stesso modo.0crea uno stacking context;autono. - Modali dentro componenti molto annidati. Mettili verso la fine di
<body>(oppure usa il top layer dell'elemento<dialog>), così nessun contesto antenato può intrappolarli.
Domande frequenti
Cosa fa z-index?
Imposta l'ordine di sovrapposizione degli elementi che si sovrappongono: un valore più alto viene disegnato davanti a uno più basso all'interno dello stesso stacking context. Il valore predefinito è auto, e i valori sono numeri interi, compresi quelli negativi.
Perché il mio z-index non funziona?
O l'elemento non è posizionato (z-index ha bisogno di un position diverso da static, oppure di un figlio flex o grid), oppure si trova dentro un genitore che forma uno stacking context con un ordine più basso. Un figlio non può mai salire sopra un elemento sotto il quale è posto il suo stacking context, qualunque sia il suo z-index.
Cos'è uno stacking context?
Un gruppo di elementi che vengono impilati insieme come un unico livello. Al suo interno, i figli sono ordinati in base al loro z-index; all'esterno, l'intero gruppo viene posizionato in base allo z-index dell'elemento che l'ha creato.
Cosa crea uno stacking context?
Tra gli altri: l'elemento radice, un elemento posizionato con uno z-index diverso da auto, position: fixed o sticky, un figlio flex o grid con uno z-index, opacity minore di 1, transform, filter, isolation: isolate e will-change su quelle proprietà.
z-index funziona senza position?
Non sui normali elementi block o inline: position: static lo ignora. Funziona invece sugli elementi flex e grid senza alcun position.