Articolo originale: 4 reasons your z-index isn’t working (and how to fix it) di Jessica Chan

Tradotto e adattato da: Ilenia Magoni

Questo post è stato pubblicato in origine su Coder-Coder.com.

Z-index è una proprietà CSS che ti permette di posizionare elementi in livelli uno sull'altro. È molto utile, e onestamente uno strumento molto importante da conoscere usando CSS.

Sfortunatamente, z-index è una di quelle proprietà che non funziona sempre in maneira intuitiva. Sembra semplice all'inizio: un numero z-index più alto significa che l'elemento sarà sopra gli elementi con un z-index inferiore. Ma ci sono regole aggiuntive che possono rendere le cose più complicate. E non puoi risolvere tutto assegnando un z-index di 999999!

Questo articolo spiegherà in dettaglio quattro delle ragioni più comuni per cui il z-index non sta funzionando per te, e esattamente come puoi fare per sistemarlo.

Guarderemo ad alcuni esempi di codice e risolveremo i loro problemi. Dopo aver letto questo articolo sarai in grado di capire e evitare questi errori comuni con il z-index!

Guarda la versione video [in inglese] di questo articolo sul mio canale YouTube, Coder Coder.

Guardiamo alla prima ragione:

1. Elementi nello stesso contesto di stacking saranno mostrati in ordine di apparizione, con elementi successivi sopra elementi precedenti.

In questo esempio abbiamo un layout relativamente semplice che include tre elementi principali:

  • L'immagine di un gatto
  • Un riquadro bianco con testo
  • Un'altra immagine dello stesso gattoAnother image of the same cat

Ecco il markup HTML per questo esempio:

<div class="cat-top"></div> 

<div class="content__block"> Meow meow meow... </div> 

<div class="cat-bottom"></div>

In questo layout vogliamo idealmente il riguadro bianco con testo sopra entrambi i gatti.

Per provare a ottenere ciò abbiamo aggiunto un margine negatico ad entrambe le immagini dei gatti, così che si sovrappongono leggermente al riquadro bianco:

.cat-top { 
   margin-bottom: -110px; 
} 

.cat-bottom { 
   float: right; 
   margin-top: -120px; 
}

Ma, la situazione è questa:

Il primo gatto è posizionato sotto il riquadro bianco, esattamente come vogliamo. ma il secondo gatto è posizionato sopra il riquadro!

Perché sta succedendo?

La ragione di questo comportamento è data dal ordine di stacking naturale sulla pagina. Queste linee guida in pratica determinano quali elementi saranno sopra altri e quali saranno sotto.

Anche se gli elementi non hanno un z-index assegnato c'è una ragione per quale sarà sopra.

Nel nostro caso nessuno degli elementi ha un z-index. Il loro stacking è determinato dal loro ordine di apparizione. Secondo questa regola, gli elementi che vengono dopo nel markup saranno sopra gli elementi che vengono prima.

(Puoi leggere più informazioni sulle linee guida dell'ordine di stacking su Mozilla Developer Network qui.)

Nel nostro esempio con i gatti e il riquadro bianco, stanno obbedendo a queste regole. Questa è la ragione per cui il primo gatto è sotto il blocco bianco e il blocco bianco è sotto il secondo gatto.

Ok, l'ordine di stacking è interessante, ma come sistemiamo la cosa così che anch eil secondo gatto è sotto il riquadro bianco?

Passiamo alla seconda ragione:

2. L'elemento non ha una proprietà position

Una delle altre regole che determinano l'ordine di stacking è se l'elemento ha una posizione assegnata o meno.

Per dare una posizione a un elemento, aggiungi la proprietà CSS position con un valore qualsiasi tranne che static, come relativeo absolute.

Secondo questa regola, gli elementi con la proprietà position appariranno sopra gli elementi che non ce l'hanno.

Quindi dare al riquadro bianco la prorpietà position: relative, senza dare ai due gatti una proprietà position metterà il riquadro bianco sopra i due gatti nell'ordine di stacking.

Così è come apparirà. Puoi anche sperimentare con la pen di Codepen linkata sopra.

NlDhNhhBXrXmR35aZCt4XCGbfBCt4bRPLHzK

Evvai!

Ora, la prossima cosa che vogliamo fare è ruotare il gatto in basso sottosopra, usando la proprietà transform. In questo modo entrambti i gatti saranno sotto il blocco bianco, mostrando solo la testa.

Ma facendo ciò può causare più confusione legata al z-index. Affronteremo il problema e la soluzione nella prossima parte.

3. Dare ad un elemento proprietà CSS come opacity o transform mette l'elemento in un nuovo contesto di stacking.

Come appena menzionato, vogliamo capovolgere il gatto in basso. Per farlo aggiungiamo transform: rotate(180deg).

.cat-bottom { 
   float: right; 
   margin-top: -120px; 
   transform: rotate(180deg); 
}

Ma questo fa sì che il gatto in basso appaia di nuovo sopra il riquadro bianco!

GTJjexmzYUkJa37hDuIUALqGngUjSl0wxFcE

Che cavolo sta succedendo qui??

Potresti non incontrare questo problema spesso, ma un altro aspetto dell'ordine di stacking è che alcune proprietà come transform o opacity mettono l'elemento in un nuovo contesto di stacking.

Questo significa che aggiungendo la proprietà transform all'elemento .cat-bottom fa sì che si comporti come se avesse uno z-index di 0. Anche se non ha affatto una proprietà position o z-index! (W3.org ha della documentazione informativa ma noiosa su come questo funziona con la proprietà opacity)

Ricorda, non abbiamo mai aggiunto uno z-index al riquadro bianco, solo position: relative, ed è stato abbastanza per portate il riquadro bianco sopra i gatti non posizionati.

Ma visto che l'elemento .bottom-cat si sta comportando come se avesse una posizione relativa con z-index: 0, trasformandolo è stato posizionato sopra il riquadro bianco.

La soluzione è dare  position: relative e mettere uno z-index esplicito almeno sul riquadro bianco. Potresti portarlo uno step più in la e dare position: relative e un0 z-index più basso al gatto, giusto per andare sul sicuro.

.content__block { 
   position: relative; 
   z-index: 2; 
} 

.cat-top, .cat-bottom { 
   position: relative; z-index: 1; 
}

Il mio parere è che fare ciò risolverà la maggior parte, se non tutti, i problemi base con z-index.

Ora, affrontiamo l'ultima ragione per cui il z-index non sta funzionando. Qui si va un po' più sul complesso, involvendo elementi genitori e figli.

4. L'elemento è in un contesto di stacking più basso a causa del z-index dell'elemento genitore

Vediamo l'esempio per questo caso:

Abbiamo una semplice pagina con contenuto regolare, e un tab a lato che dice "Send Feedback" posizionato sopra il contenuto.

E quando clicchi sulla foto del gatto, l'elemento .modal appare con un background grigio semi-trasparente sovrapposto alla pagina.

Ma quando l'elemento .modal appare, il tab a lato è comunque sopra di esso, anche se vogliamo che sia sopra a tutto.

Diamo un'occhiata al CSS degli elementi in questione:

.content { 
   position: relative; 
   z-index: 1; 
} 

.modal { 
   position: fixed; 
   z-index: 100; 
} 

.side-tab { 
   position: fixed; 
   z-index: 5; 
}

Tutti gli elementi hanno una proprietà posizione, e il tab a lato ha un z-index di 5, il che lo posiziona al di sopra dell'elemento .content che ha un z-index di 1.

Poi abbiamo l'elemento .modal, che ha un z-index di 100, il che dovrebbe posizionarla sopra .side-tab col suo z-index di 5, ma invece è il tab che appare sopra.

Perché?

Abbiamo visto più sopra alcuni fattori che influenzano il contesto di stacking, come se l'elemento ha una proprietà position e il suo ordine nel markup.

Ma un altro aspetto del contesto di stacking è che un elemento figlio è limitato al contesto di stacking dell'elemento genitore.

Guardiamo più da vicino i tre elementi in questione.

Il markup che abbiamo è questo:

<section class="content">            
    <div class="modal"></div>
</section>

<div class="side-tab"></div>

Guardando al markup possiamo vedere che .content e .side-tab sono fratelli, cioè esistono allo stesso livello nel markup (è una cosa diversa rispetto al livello z-index). E l'elemento .modal è discendente di .content.

Essendo .modal dentro .content, il suo z-index di 100 ha un effetto solo dentro il suo elemento genitore. Per esempio, se ci fossero stati altri elementi figli di .content il loro z-index li metterebbe uno sull'altro o uno sotto l'altro.

Ma il valore del z-index di quegli elementi figli non ha significato al di fuori dell'elemento genitore che ha invece un z-index di 1.

Quindi i suoi elementi figli, .modalincluso, non possono uscire da quel livello di z-index.

(Puoi ricordarlo con questa metafora un poì deprimente: un figlio può essere limitato dai suoi genitori e non può liberarsi di loro.)

Ci sono un paio di soluzioni per questo problema:

Soluzione: muovi .modal al di fuori dell'elemento .content e nel contesto di stacking principale della pagina.

Il markup corretto sarebbe quindi:

<section class="content"></section>

<div class="modal"></div>

<div class="side-tab"></div>

Ora, l'elemento .modal è fratello degli altri, così da avere tutti gli elementi nello stesso contesto di stacking, e in modo tale che il loro livello di z-index abbia effetto gli uni sugli altri.

In questo contesto di stacking gli elementi appaiono nel seguente ordine, partendo dall'alto:

  • modal (z-index: 100)
  • side tab (z-index: 5)
  • content (z-index: 1)

Soluzione alternativa: rimuovi la posizione dall'elemento content così che non limiti il z-index di modal.

Se non vuoi o non puoi cambiare il markup, puoi risolvere questo problema rimuovendo la posizione dall'elemento content.

.content { 
   /* senza proprietà posizione */
} 

.modal { 
   position: absolute; 
   z-index: 100; 
} 

.side-tab { 
   position: absolute; 
   z-index: 5; 
}

Visto che l'elemento content adesso non ha una posizione, non limita più il z-index di modal e questo sarà posizionato sopra side-tab visto il suo valore più alto di z-index di 100.

Questo metodo funziona, ma personalmente opterei per la prima soluzione.

Perché se per qualche ragione devi dare una posizione all'elemento content, limiterà di nuovo l'ordine di modal nel contesto di stacking.Because if for some reason in the future you have to position the content element, it will again limit the modal’s order in the stacking context.

In sintesi

Spero che tu abbia trovato questa guida utile! Per riassumente, la maggior parte dei problemi con lo z-index possono essere risolti seguento le seguenti linee guida:

  1. Controlla che gli elementi abbiano la proprietà position e che i numeri di z-index siano nell'ordine corretto.
  2. Assicurati di non avere elementi genitori che limitano il livello z-index degli elementi figli.