Quando crei tooltip o popover con il posizionamento degli ancoraggi CSS, il browser può "capovolgere" automaticamente l'elemento in una posizione di riserva se altrimenti uscirebbe dalla visualizzazione. In questo caso, potresti voler modificare lo stile dei contenuti posizionati, ad esempio per riposizionare una freccia che punta dai contenuti posizionati all'ancoraggio.
Le query container ancorate risolvono questo problema consentendoti di eseguire query sullo stato di posizionamento attivo di un elemento e di applicare gli stili di conseguenza. Per il posizionamento generale di menu a discesa e menu extra ancorati con inversione della collisione con l'area visibile (senza restyling della freccia direzionale), consulta Menu a discesa sensibili all'area visibile.
Il problema
Immagina un tooltip che viene visualizzato sopra l'ancora per impostazione predefinita. Ha una freccia "giù" in basso. Se l'utente scorre e la descrizione comando si capovolge per apparire sotto l'ancora, la freccia punta nella direzione sbagliata e si trova sul lato sbagliato della descrizione comando.
La soluzione: query container ancorate
Impostando container-type: anchored sull'elemento posizionato, lo trasformi in un contenitore di query che conosce il proprio stato di posizionamento ancorato. Puoi quindi utilizzare la query @container anchored() per aggiornare i relativi discendenti o pseudo-elementi.
1. Crea il tooltip e il trigger
Utilizza l'API Popover per creare un tooltip. La chiamata del popover tramite popovertarget stabilisce automaticamente una connessione di ancoraggio implicita con il pulsante di attivazione, quindi non è necessario un anchor-name o un position-anchor esplicito.
<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>
Reimposta gli stili di inset e margine del popover per l'utilizzo con il posizionamento dell'ancoraggio, ma solo se il posizionamento dell'ancoraggio è supportato.
@supports (anchor-name: --my-anchor) {
[popover] {
inset: auto;
margin: unset;
}
}
2. Configura il container
Applica container-type: anchored all'elemento da posizionare. Questo elemento deve avere anche position-try-fallbacks definito per attivare il comportamento di inversione.
#tooltip {
position: fixed;
position-area: block-start;
position-try-fallbacks: flip-block;
/* Enable anchored container queries */
container-type: anchored;
}
3. Stile basato sul fallback
Utilizza @container anchored(fallback: <value>) per applicare gli stili quando è attivo un determinato elemento di riserva.
Come tutte le query container, @container può applicare lo stile solo ai discendenti del container. Una strategia comune per creare le frecce è utilizzare gli pseudo-elementi ::before e ::after, che vengono trattati come discendenti e possono essere formattati direttamente. Tuttavia, per applicare lo stile al tooltip stesso (come mostrato nel passaggio 4), aggiungeremo un elemento secondario al tooltip e creeremo la freccia nel suo pseudo-elemento ::before.
<div id="tooltip" popover role="tooltip">
<div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
/* Default "down" arrow for the 'top' position */
content: "▼";
position: absolute;
inset-block-end: 0;
inset-inline-start: 1rem;
}
/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
.tooltip-content::before {
content: "▲";
inset-block-start: 0;
inset-block-end: auto;
}
}
4. Stilizzazione del container stesso
Se devi modificare le proprietà del contenitore stesso (come margin o background-color) quando si capovolge, devi utilizzare un elemento wrapper interno.
- Applica
container-type: anchoredall'elemento posizionato esternamente. - Scegli come target l'elemento interno all'interno del blocco
@container.
@container anchored(fallback: flip-block) {
.tooltip-content {
border-radius: 0 0 .5rem .5rem;
margin-block-start: 0.25rem;
}
}
Best practice
- Preferisci i fallback logici: utilizza parole chiave come
flip-blockeflip-inlineinposition-try-fallbacksper query più semplici che gestiscono automaticamente la scrittura da destra a sinistra e diverse modalità di scrittura. - Utilizza gli pseudo-elementi per le frecce: le frecce dei tooltip sono puramente decorative e sono perfette per
::beforeo::after, che possono essere stilizzati tramite query del contenitore ancorato senza DOM aggiuntivo.
Strategie di riserva
Il posizionamento della freccia in base al fallback applicato è un potenziamento progressivo e non esiste un altro modo per reagire alla posizione di fallback. Per nascondere la freccia nei browser che non supportano le query container di posizione di ancoraggio, verifica il supporto CSS con @supports (container-type: anchored).
@supports (container-type: anchored) {
.tooltip-content::before {
content: "▼";
}
}
Alternative e supporto del browser per Popover
L'API Popover è per lo più un potenziamento progressivo, ma i suoi comportamenti distintivi (promozione al livello superiore, chiusura con un clic e attivazione di popovertarget) non hanno un equivalente solo CSS. I browser meno recenti richiedono un polyfill o un fallback manuale se preferisci non fornirne uno.
Polyfill: per supportare l'attributo popover nei browser meno recenti, carica @oddbird/popover-polyfill in modo condizionale. OBBLIGATORIO: esegui il rilevamento delle funzionalità controllando la proprietà popover su HTMLElement.prototype e carica il polyfill solo quando manca il supporto nativo; NON caricarlo incondizionatamente.
Con un bundler o una mappa di importazione:
// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
import("@oddbird/popover-polyfill");
}
Senza un bundler, importa da una CDN all'interno di un <script type="module">:
<script type="module">
if (!("popover" in HTMLElement.prototype)) {
import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
}
</script>
Avvertenza sullo stile: il polyfill non può definire la pseudo-classe :popover-open reale, quindi applica una classe .\:popover-open. OBBLIGATORIO: combina i due elementi con :is() o :where(), altrimenti i browser che non dispongono di :popover-open ignorano l'intera regola:
[popover]:is(:popover-open, .\:popover-open) {
display: block;
}
In alternativa, per un fallback legacy senza un polyfill, utilizza position: fixed e calcola manualmente le coordinate tramite getBoundingClientRect() o affidati al posizionamento predefinito con inset: auto se è accettabile per il caso d'uso.
I browser che non supportano l'API Popover non supportano nemmeno il posizionamento degli ancoraggi, quindi il tooltip verrà visualizzato al centro dello schermo.