CSS z-index non funziona? Stacking context, vista 3D | We.Inc
Perché z-index viene ignorato, ogni proprietà che crea uno stacking context, una vista 3D esplosa dei livelli, header sticky e dropdown, una scala di z-index e una checklist di debug.
z-index ordina gli elementi sovrapposti, ma solo all'interno dello stesso stacking context. Un figlio con z-index: 9999 non può salire sopra un elemento esterno al genitore se quel genitore forma un contesto con uno z-index più basso. I contesti nascono da position più z-index, opacity sotto 1, transform, filter, isolation: isolate e diverse altre proprietà.
Perché z-index sembra ignorato
Sintomo
Causa probabile
z-index non ha effetto
L'elemento è position: static e non è figlio di flex o grid
Uno z-index enorme resta comunque dietro
Un antenato forma uno stacking context su un livello più basso
Dropdown nascosto sotto la sezione successiva
Il genitore ha transform, opacity o filter
Menu tagliato sul bordo
overflow: hidden su un antenato, non è affatto z-index
La vista 3D qui sotto scompone una piccola pagina nei suoi livelli di stacking, così puoi vedere quali box sono intrappolati in quale contesto. Cambia i valori di z-index e attiva o disattiva sul genitore la proprietà che crea un contesto. Dopo: ogni trigger secondo MDN, header sticky con dropdown, una scala di token e una procedura di debug passo per passo.
Imposta i valori di z-index per l'header, la card e il dropdown dentro la card.
Attiva sulla card un trigger di stacking context e guarda il dropdown restare intrappolato.
Attiva la vista 3D per vedere i livelli separati e raggruppati per contesto.
Usa isolation: isolate o sposta il dropdown fuori dal contesto per risolvere.
Prima di alzare un numero, trova lo stacking context. Alzare z-index dentro un contesto che intrappola non serve mai.
Tieni i valori di z-index in token con un nome e lascia spazio tra l'uno e l'altro, così i nuovi livelli si inseriscono senza rinumerare.
Usa isolation: isolate sui componenti per contenere i loro z-index interni, così non possono entrare in conflitto con il resto della pagina.
Per modali e popover, l'elemento nativo dialog e l'attributo popover usano il top layer, che sta sopra qualsiasi z-index.
Domande frequenti
Perché z-index non funziona?
O l'elemento non è posizionato (z-index richiede un position diverso da static, oppure un genitore flex o grid), o è intrappolato in uno stacking context. Il risultato lo decide la posizione del genitore nel proprio contesto, e i figli non possono sfuggirgli, qualunque numero abbiano.
Cosa crea uno stacking context?
L'elemento radice, gli elementi posizionati con uno z-index, gli elementi fixed e sticky, i figli di flex e grid con uno z-index, opacity sotto 1, transform, filter, clip-path, maschere, mix-blend-mode, perspective, isolation: isolate, alcuni valori di contain e will-change, i size container e gli elementi del top layer.
Cosa fa isolation: isolate?
Crea un nuovo stacking context e nient'altro, senza alcun cambiamento visivo. Mettilo sulla radice di un componente così i figli con z-index negativo restano dietro lo sfondo del componente invece di finire dietro la pagina, e i suoi livelli interni non si mescolano mai con quelli esterni.
Come tengo un dropdown sopra la sezione successiva?
Dai all'header o al contenitore del dropdown uno z-index più alto delle sezioni che seguono, con entrambi posizionati. Se il contenitore ha un transform o un'opacity, ricorda che forma un proprio contesto, quindi lo z-index va su quel contenitore, non sul dropdown.
Uno z-index negativo è sicuro?
È valido, ma l'elemento va dietro lo sfondo del suo stacking context. Senza un contesto sul genitore, questo può significare dietro lo sfondo della pagina, quindi invisibile. Aggiungi isolation: isolate sul genitore per tenerlo dentro.
Come funziona l'ordine di disegno
All'interno di uno stacking context il browser disegna in un ordine fisso: lo sfondo del contesto, poi i figli con z-index negativo, poi il normale contenuto a blocchi, i float, il contenuto inline, gli elementi posizionati con z-index auto o 0 nell'ordine del sorgente e infine gli z-index positivi dal più basso al più alto.
Un contesto figlio viene disegnato come un'unica unità nella posizione del genitore in quella lista. Tutto ciò che contiene viene ordinato solo rispetto ai suoi fratelli. È l'unico motivo per cui un 9999 dentro una card con z-index: 1 perde contro un vicino con z-index: 2.
Una procedura di debug
Prima conferma che sia un problema di stacking: se l'elemento è tagliato lungo un bordo dritto, cerca invece un overflow su un antenato. Poi risali dall'elemento nascosto nei DevTools, controllando negli stili calcolati di ogni antenato i trigger elencati in questa pagina.
I DevTools di Chromium hanno un pannello Layers ed Edge ha una 3D View che mostrano visivamente i livelli compositi. Una volta trovato l'antenato che forma il contesto, alza quell'antenato, rimuovi il trigger o esegui il rendering dell'elemento flottante fuori da esso.
Tutto ciò che crea uno stacking context
Basato sul riferimento MDN sullo stacking context. Basta una sola condizione.
Trigger di stacking context
Proprietà o stato
Condizione
Elemento radice
html è sempre lo stacking context radice
position: absolute o relative
Solo con uno z-index diverso da auto
position: fixed o sticky
Sempre, z-index non necessario
Figlio di flex o grid
Con uno z-index diverso da auto, anche se position è static
container-type: size o inline-size
Qualsiasi elemento che sia un size query container
opacity sotto 1
Compreso opacity: 0.99
Qualsiasi valore diverso da normal
transform, scale, rotate, translate
Qualsiasi valore diverso da none
filter o backdrop-filter
Qualsiasi valore diverso da none
Qualsiasi valore diverso da none
Qualsiasi valore diverso da none
mask, mask-image, mask-border
Qualsiasi valore diverso da none
isolation: isolate
Pensato esattamente per questo scopo, senza effetti visivi collaterali
Indicare qualsiasi proprietà che, se impostata, creerebbe uno stacking context
layout, paint o una scorciatoia che li include (strict, content)
Top layer
Dialog modale aperto, popover, elemento a schermo intero e il loro ::backdrop
La trappola e le soluzioni
Uno z-index 9999 che perde comunque
La card blu è un contesto a z-index 1. Il suo tooltip ha 9999 ma viene confrontato solo con ciò che sta dentro la card, quindi il box arancione a z-index 2 lo copre.
isolation: isolate tiene dentro un livello negativo
Senza isolate, la decorazione con z-index: -1 finirebbe dietro lo sfondo della sezione e sparirebbe. Con isolate, la sezione è un contesto a sé.
Header sticky con un dropdown
L'header è sticky, quindi è già un contesto. Dagli uno z-index sopra il contenuto e il dropdown al suo interno eredita quel livello. Nessun numero enorme necessario.
Contenuto normale
Card sollevate all'hover, intestazioni di tabella sticky
Menu, elenchi di autocompletamento
Header del sito sticky
Sfondo del drawer
Modali personalizzati (il dialog nativo usa invece il top layer)
Notifiche che devono stare sopra tutto
Laboratorio di stacking con vista 3D esplosa
z-index dell'header
z-index della card (o auto)
z-index del dropdown
z-index del banner
Trigger di contesto sulla card
Proprietà aggiuntiva sulla card
Vista 3D esplosa (ruota i livelli separandoli)
Livelli separati, più in alto significa disegnato dopo
Vista piatta, CSS reale
Header z {z}
Card z {z}
Dropdown z {z}
Banner z {z}
(dentro la card)
sopra il banner
sotto il banner
La card forma uno stacking context ({why}). Lo {d} del dropdown conta solo dentro la card, quindi è {pos} perché lo è la card.
La card non è uno stacking context, quindi il dropdown compete direttamente: {d} contro {b} del banner. È {pos}.
CSS per questa configurazione
Copia il CSS
Prova: card z auto, dropdown 9999, poi scegli transform. Una sola proprietà intrappola il dropdown.