Fade e slide fluidi anche quando l’elemento entra/esce dal layout, con poche righe di CSS moderno.
Il problema: display: none non si anima (ma l’UI sì)
Quando un componente passa da display: none a display: block (o viceversa) non c’è interpolazione possibile: o è nel layout oppure no. Per questo molti pattern storici usano alternative come opacity + visibility, wrapper che restano nel DOM, oppure trucchi con max-height.
Nel CSS moderno però possiamo ottenere transizioni “pulite” anche quando entra in gioco un cambio discreto (come display), coordinandolo con proprietà interpolabili (opacity, transform, ecc.).
L’idea: transizioni miste (discrete + interpolabili)
Il pattern è:
-
Stato “chiuso”: l’elemento ha i valori finali dell’uscita (es.
opacity: 0e una traslazione). -
Stato “aperto”: l’elemento passa a
opacity: 1e torna in posizione. -
Transizione: abilitiamo la transizione anche per le proprietà discrete con
transition-behavior: allow-discrete. -
Ingresso coerente: usiamo
@starting-styleper definire i valori iniziali solo all’apertura (fondamentale per vedere l’animazione in entrata quando l’elemento “compare”).
Nota: l’esempio qui sotto usa un popover (top-layer), ma il concetto è applicabile a qualsiasi UI che alterna
display: none/visibile. Per top-layer, ha senso includere ancheoverlay.
Esempio completo: fade + slide per un popover
1) Base: stato chiuso + transizioni
.my-popover {
/* Stato di uscita (chiuso) */
opacity: 0;
transform: translate(0, 30px);
/* Transizioni: includiamo anche le proprietà discrete */
transition-property: display, opacity, transform, overlay;
transition-duration: 200ms;
transition-timing-function: ease;
/* Abilita la transizione delle proprietà discrete (es. display/overlay) */
transition-behavior: allow-discrete;
}
-
opacityetransformsono interpolabili, quindi animano normalmente. -
displayeoverlaysono discrete: senzaallow-discretelo switch sarebbe “secco”. -
overlayha senso quando stai lavorando con elementi in top-layer (popover/modali).
2) Stato aperto: rendi visibile e imposta il layout qui
Con un popover nativo puoi usare l’attributo :popover-open.
.my-popover:popover-open {
opacity: 1;
transform: translate(0, 0);
/* Importante: imposta il display SOLO quando è aperto */
display: grid;
}
Perché display: grid solo qui?
- Se lo metti nella regola base, l’elemento potrebbe risultare “sempre presente” dal punto di vista del layout.
- In generale, tutti i cambi di display vanno legati allo stato aperto, non allo stato chiuso.
3) L’ingrediente che sblocca l’entrata: @starting-style
Senza questo, spesso noterai che la chiusura anima correttamente, ma l’apertura no (perché il browser non ha un “valore iniziale animabile” al momento in cui l’elemento entra nel rendering).
@starting-style {
.my-popover:popover-open {
opacity: 0;
transform: translate(0, -30px);
}
}
Cosa ottieni:
-
Apertura: parte da
opacity: 0etranslateY(-30px)e transiziona versoopacity: 1etranslateY(0). -
Chiusura: torna verso lo stato base (
opacity: 0etranslateY(30px)), quindi puoi anche avere una direzione diversa in uscita.
Dettagli pratici (che evitano glitch)
-
Direzione diversa tra entrata e uscita: come nell’esempio, usa
@starting-styleper l’entrata (es.-30px) e la regola base per l’uscita (es.+30px). -
Layout e proprietà “strutturali”: imposta
displaynello stato aperto, ma valuta caso per caso proprietà comegrid-template-columns. Se cambiano drasticamente, può essere meglio mantenerle coerenti tra stati per evitare salti inattesi durante la transizione. - Durate: 150–250ms di solito sono più che sufficienti per popover e menu; durate più lunghe evidenziano eventuali imperfezioni.
Sintesi
Con transition-behavior: allow-discrete e @starting-style puoi finalmente gestire in modo elegante la transizione di componenti che entrano/escono dal layout (anche partendo da display: none), combinando cambi discreti e animazioni fluide su opacity e transform. Il risultato è un’UI più coerente, senza wrapper extra e senza hack: lo stato chiuso definisce l’uscita, @starting-style definisce l’ingresso, e lo stato aperto contiene anche le scelte di display.
Articolo originale: https://frontendfacile.it/blog/animare-l-apertura-chiusura-da-display-none-senza-hack-transition-behavior-e-sta
Top comments (0)