JavaScript: altezze calcolate degli elementi e display:none

Short link

In questo articolo vedremo cosa succede al modello di layout degli elementi HTML quando usiamo questa particolare dichiarazione CSS.

La proprietà CSS display ci consente di specificare un modello di layout per gli elementi HTML. Quando si dichiara un modello di layout, i browser selezionano internamente un algoritmo specifico che verrà applicato al rendering finale degli elementi HTML.

Quando dichiariamo display: none, stiamo effettivamente eseguendo un hard reset del modello di layout predefinito di un dato elemento. La conseguenza più importante di ciò da un puro punto di vista JavaScript è che le dimensioni calcolate sono completamente azzerate, in particolare le altezze.

Supponiamo di voler mostrare un overlay modale su una pagina. Possiamo creare la seguente struttura HTML.

<html>
<body>
    <main id="site"></main>
    <div id="overlay"></div>
</body>
</html>

Ora, quando mostriamo l'overlay, vogliamo nascondere il contenitore del sito principale con display: none. La nostra finestra modale dovrebbe avere un'altezza uguale all'altezza complessiva della finestra. Possiamo scrivere il seguente codice CSS:

#overlay {
    width: 100%;
    min-height: 100vh;
    position: absoute;
    top: 0;
    left: 0;
    z-index: 100000;
    background-color: #fff;
    display: none;
}

Questo è lo scenario più semplice che possiamo gestire. Quando l'overlay passa da none a block, i browser visualizzano la dichiarazione min-height: 100vh, applicabile a un modello di layout a blocchi, e automaticamente regola l'altezza calcolata dell'elemento sul valore desiderato. Fin qui tutto bene.

Ma cosa succede a #site? In poche parole, ora la sua altezza calcolata è zero. In questo caso questo non è un problema, perché non è necessario tenerne conto quando si desidera visualizzare il nostro elemento.

La domanda è: qual è l'altezza effettiva calcolata dell'oggetto document quando applichiamo display: none a un elemento? La risposta è semplice: è data dall'altezza calcolata di tutti gli elementi che hanno ancora un valore display diverso da none meno l'altezza calcolata originale di tutti gli elementi che ora hanno la dichiarazione display: none.

Nel nostro esempio, l'altezza calcolata dell'oggetto document è zero. Come abbiamo detto prima, questo non è un problema perché il nostro elemento ha una dichiarazione di min-height: 100vh e non ci sono altri elementi principali in quella pagina.

I problemi sorgono quando il nostro elemento overlay deve avere un'altezza dinamica calcolata tramite JavaScript. In questo caso non possiamo semplicemente assegnare un'altezza minima statica ma in realtà dobbiamo specificare un'altezza uguale all'altezza originale dell'oggetto document.

La soluzione è salvare l'altezza calcolata originale prima di nascondere e mostrare gli elementi (si veda la pagina di riferimento MDN).

'use strict';

const originalHeight = document.body.clientHeight;
const overlay = document.querySelector('#overlay');
const site = document.querySelector('#site');

site.style.display = 'none';
overlay.style.minHeight = originalHeight + 'px';
overlay.style.display = 'block';

Altre due domande:

  1. Perché abbiamo usato absolute invece di fixed?
  2. Perché abbiamo usato min-height invece di height?

La risposta è semplice: la proprietà overflow. Quando abbiamo un contenuto predeterminato, come una singola immagine o video con dimensioni fisse, non importa quale algoritmo di posizionamento o di altezza abbiamo scelto.

Ma quando abbiamo alcuni contenuti dinamici con altezze variabili, come un elenco di post di un blog, scegliendo l'algoritmo ad altezza fissa costringeremo i browser a decidere se mostrare o meno un meccanismo di scorrimento. Ciò è particolarmente evidente sui dispositivi mobili, dove si ottiene l'effetto indesiderato di avere una parte dei nostri contenuti che non è visibile a causa del fatto che lo scorrimento della pagina si interrompe alla fine della finestra e non va oltre.

L'autore

Gabriele Romanato, sviluppatore web full stack specializzato in siti, applicativi web ed e-commerce con Node.js e PHP.