1 luglio 2026
Smettila di sprecare tempo con JavaScript: i popover moderni si fanno (anche) in CSS
Con l’attributo `popover`, `::backdrop` implicito, transizioni discrete e un pizzico di anchoring, puoi ottenere apertura/chiusura accessibili con pochissimo codice.
I popover non sono più un esercizio obbligatorio di JavaScript. Oggi il browser offre un’API nativa: un bottone che apre/chiude, light dismiss, ESC, gestione del focus e stati CSS da animare. In questo articolo vediamo un’implementazione minimale e pulita, con fade e slide controllati da CSS, inclusa la transizione per proprietà discrete e un accenno al posizionamento vicino al trigger tramite anchoring.
Negli ultimi anni abbiamo accumulato un riflesso quasi automatico: “serve un popover? scrivo due righe di JavaScript”. Il problema non è il JS in sé, è che spesso lo usiamo per ricreare comportamenti che il browser può già gestire meglio (e con più attenzione all’accessibilità) in modo nativo.
Oggi i popover possono essere realizzati con HTML + CSS in modo estremamente compatto, ottenendo gratis:
- Apertura/chiusura senza handler
- Light dismiss (clic fuori per chiudere)
- Tasto ESC
- Comportamenti di base più prevedibili e “browser-native”
E, soprattutto, puoi animarli con CSS in maniera pulita.
Il popover nativo: markup minimo
L’idea è semplice:
- Un elemento “contenitore” che dichiari
popover - Un bottone che lo controlli con
popovertarget
<button popovertarget="my-popover">Apri popover</button>
<div id="my-popover" popover>
Contenuto del popover
</div>
Con solo questo, il bottone apre/chiude il popover. E sì: funziona anche con ESC e clic fuori, senza dover “reinventare” niente.
Nota: esistono varianti e attributi correlati (ad es. modalità diverse), ma questo è lo scheletro più immediato per partire.
Styling e animazione: lo stato :popover-open
Quando il popover è visibile, puoi selezionarlo via pseudo-classe:
:popover-open→ popover attualmente aperto
Partiamo con un semplice fade.
#my-popover {
opacity: 0;
transition: opacity 300ms ease;
}
#my-popover:popover-open {
opacity: 1;
}
Fin qui sembra tutto normale… ma c’è un dettaglio importante.
Transizioni che funzionano davvero: transition-behavior: allow-discrete
L’apertura/chiusura di un popover coinvolge anche cambiamenti “discreti” (non interpolabili) legati al rendering/visibilità. Risultato tipico: l’animazione entra, ma in chiusura “sparisce di colpo”.
Per consentire transizioni più sensate anche in questi casi, puoi aggiungere:
#my-popover {
transition-behavior: allow-discrete;
}
In pratica stai dicendo al browser: “consenti la transizione anche quando ci sono step discreti nel mezzo”.
Animare anche la posizione: slide + fade con translate
Una combinazione molto naturale è fade + slide. Ad esempio: entra dal basso e esce verso l’alto (o viceversa).
#my-popover {
opacity: 0;
translate: 0 50px;
transition:
opacity 300ms ease,
translate 300ms ease;
transition-behavior: allow-discrete;
}
#my-popover:popover-open {
opacity: 1;
translate: 0 0;
}
@starting-style {
#my-popover:popover-open {
opacity: 0;
translate: 0 -50px;
}
}
Cosa succede qui:
- Stato chiuso:
opacity: 0etranslate: 0 50px - Stato aperto:
opacity: 1etranslate: 0 0 - Con
@starting-stylepuoi definire lo stato iniziale al momento dell’apertura, rendendo l’entrata più controllata
È un pattern molto utile quando vuoi evitare “salti” tra calcolo layout e primo frame dell’animazione.
Posizionarlo vicino al trigger: cenni di anchoring
Un popover spesso ha senso in relazione al bottone che lo apre. Il CSS moderno offre strumenti per agganciare un elemento a un altro (anchoring), riducendo la necessità di calcoli JS per “metterlo sotto al bottone”.
A livello concettuale:
- definisci un’ancora (il trigger)
- posizioni il popover rispetto a quell’ancora (ad es. “sotto”)
La sintassi e il supporto possono variare, ma il punto pratico è questo: se il tuo popover è un componente ricorrente, l’anchoring ti evita coordinate hard-coded o getBoundingClientRect() per casi semplici.
Implicazione pratica: JS dove serve, non per abitudine
Non è una crociata contro JavaScript. È una questione di allocare complessità nel posto giusto:
- Se ti serve un popover standard (apri/chiudi, ESC, clic fuori, animazione), l’HTML/CSS nativi oggi coprono già gran parte del lavoro.
- Riservare JS ai casi “veramente applicativi” (stato, dati, orchestrazione) riduce bug, codice boilerplate e regressioni sull’accessibilità.
Sintesi
Un popover moderno può essere:
- dichiarato in HTML con
popover - controllato con
popovertarget - animato con
:popover-open,@starting-styleetransition-behavior: allow-discrete - posizionato vicino al trigger con anchoring (quando disponibile)
Se stai ancora scrivendo handler e listener solo per aprire/chiudere un pannellino, probabilmente stai spendendo tempo dove il browser è già pronto a fare il lavoro per te.