CSS Anchor Positioning: Tooltip e Dropdown Senza JavaScript
Costruire un tooltip in JavaScript significa scrivere codice per calcolare la posizione dell'elemento relativa al suo trigger, aggiornare quella posizione su resize e scroll, gestire i casi edge quando il tooltip finisce fuori dal viewport, e fare tutto questo senza introdurre layout thrashing. Non e complesso, ma e codice ripetitivo che ogni applicazione reinventa da zero.
La CSS Anchor Positioning API risolve questo problema con CSS puro e dichiarativo. Con supporto browser all'86% globale all'inizio del 2026 (Chrome 125+, Edge 125+, Chrome for Android, Safari Technology Preview), la tecnica e matura per la produzione su siti che supportano browser moderni. Permette di "ancorare" un elemento a un altro come punto di riferimento per il posizionamento, con fallback automatici se non c'e abbastanza spazio.
Cosa Imparerai
- I concetti fondamentali di CSS Anchor Positioning: anchor, positioned element
- Le proprieta
anchor-nameeposition-anchor - La funzione
anchor()per il posizionamento relativo - Come implementare tooltip, dropdown e context menu in CSS puro
- I fallback automatici con
position-try-fallbacks - Come integrare con Popover API per accessibilita completa
- Progressive enhancement per browser senza supporto
I Concetti Fondamentali
CSS Anchor Positioning introduce due ruoli:
-
L'anchor element (elemento ancora): l'elemento a cui ci ancoriamo.
Riceve la proprieta
anchor-namecon un valore custom identifier (prefisso--). -
Il positioned element (elemento posizionato): l'elemento che vogliamo
posizionare relativamente all'ancora. Deve avere
position: absoluteoposition: fixed, e riceveposition-anchorper collegarsi all'ancora.
/* 1. Definisci l'ancora */
.button-trigger {
anchor-name: --tooltip-anchor;
}
/* 2. Posiziona l'elemento relativamente all'ancora */
.tooltip {
position: absolute;
/* Collega questo elemento all'ancora */
position-anchor: --tooltip-anchor;
/* Posizionamento usando la funzione anchor() */
/* anchor(bottom) = il bordo bottom dell'ancora */
top: calc(anchor(bottom) + 8px);
/* Centra orizzontalmente rispetto all'ancora */
left: anchor(center);
transform: translateX(-50%);
}
La Funzione anchor()
La funzione anchor() risolve a una coordinata relativa al bordo
specificato dell'elemento ancora. I valori disponibili sono:
anchor(top): bordo superiore dell'ancoraanchor(bottom): bordo inferiore dell'ancoraanchor(left): bordo sinistro dell'ancoraanchor(right): bordo destro dell'ancoraanchor(center): centro orizzontale dell'ancoraanchor(middle): centro verticale dell'ancoraanchor(self-start),anchor(self-end): relativi alla direzione del testo
/* Tooltip sopra il trigger */
.tooltip-top {
position: absolute;
position-anchor: --my-anchor;
bottom: calc(anchor(top) - 8px);
left: anchor(center);
transform: translateX(-50%);
}
/* Tooltip a destra del trigger */
.tooltip-right {
position: absolute;
position-anchor: --my-anchor;
top: anchor(center);
left: calc(anchor(right) + 8px);
transform: translateY(-50%);
}
/* Dropdown sotto il trigger - allineato a sinistra */
.dropdown {
position: absolute;
position-anchor: --dropdown-anchor;
top: calc(anchor(bottom) + 4px);
left: anchor(left);
min-width: anchor-size(width); /* larghezza minima = larghezza dell'ancora */
}
anchor-size(): Dimensioni Relative all'Ancora
Oltre alla funzione anchor() per le coordinate, anchor-size()
permette di accedere alle dimensioni dell'elemento ancora:
/* Il dropdown ha la stessa larghezza del trigger */
.dropdown {
min-width: anchor-size(width);
/* Altezza massima pari al 50% dell'altezza dell'ancora */
max-height: calc(anchor-size(height) * 0.5);
}
Tooltip Accessibile: CSS Anchor + Popover API
La combinazione ottimale per tooltip accessibili nel 2026 e CSS Anchor Positioning con la Popover API. La Popover API gestisce automaticamente il focus management, il click-outside per chiudere, e l'accessibilita ARIA. CSS Anchor Positioning gestisce il posizionamento visivo.
<!-- HTML: Popover API + Anchor Positioning -->
<button
popovertarget="tooltip-content"
class="btn-with-tooltip"
>
Hover per info
</button>
<div
id="tooltip-content"
popover="hint"
class="tooltip"
role="tooltip"
>
Informazione contestuale utile all'utente
</div>
/* CSS: Anchor + Popover */
.btn-with-tooltip {
anchor-name: --btn-anchor;
}
.tooltip {
/* Stili base del tooltip */
position: absolute;
position-anchor: --btn-anchor;
/* Posiziona sotto il pulsante */
top: calc(anchor(bottom) + 8px);
left: anchor(center);
transform: translateX(-50%);
/* Reset stili popover */
margin: 0;
border: 1px solid #e2e8f0;
border-radius: 6px;
padding: 8px 12px;
background: white;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
font-size: 0.875rem;
max-width: 280px;
width: max-content;
/* Animazione di entrata */
opacity: 0;
transition: opacity 0.15s ease;
/* Stato visibile (Popover API) */
&:popover-open {
opacity: 1;
}
}
/* Freccia del tooltip */
.tooltip::before {
content: '';
position: absolute;
top: -8px;
left: 50%;
transform: translateX(-50%);
border: 4px solid transparent;
border-bottom-color: #e2e8f0;
}
.tooltip::after {
content: '';
position: absolute;
top: -7px;
left: 50%;
transform: translateX(-50%);
border: 4px solid transparent;
border-bottom-color: white;
}
Dropdown Menu Completo
Un esempio piu completo: un dropdown menu da un pulsante "Azioni" con CSS Anchor Positioning e Popover API per la gestione accessibile del focus:
<!-- Bottone trigger -->
<button
class="actions-btn"
popovertarget="actions-menu"
aria-haspopup="true"
>
Azioni ▼
</button>
<!-- Menu dropdown -->
<menu
id="actions-menu"
popover="auto"
class="dropdown-menu"
>
<li><button>Modifica</button></li>
<li><button>Duplica</button></li>
<li class="separator"></li>
<li><button class="danger">Elimina</button></li>
</menu>
/* CSS del dropdown */
.actions-btn {
anchor-name: --actions-anchor;
}
.dropdown-menu {
position: absolute;
position-anchor: --actions-anchor;
/* Allinea il bordo sinistro del menu con il pulsante */
top: calc(anchor(bottom) + 4px);
left: anchor(left);
/* Larghezza minima pari al pulsante */
min-width: anchor-size(width);
/* Reset stili menu */
margin: 0;
padding: 4px 0;
list-style: none;
background: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
/* Animazione */
opacity: 0;
scale: 0.95;
transform-origin: top left;
transition: opacity 0.15s, scale 0.15s;
&:popover-open {
opacity: 1;
scale: 1;
}
}
.dropdown-menu li button {
display: block;
width: 100%;
padding: 8px 16px;
text-align: left;
border: none;
background: none;
cursor: pointer;
font-size: 0.875rem;
&:hover {
background: #f8fafc;
}
&.danger {
color: #ef4444;
}
}
.dropdown-menu .separator {
height: 1px;
background: #e2e8f0;
margin: 4px 0;
}
Fallback Automatici con position-try-fallbacks
Uno dei problemi piu noiosi dei tooltip e dei dropdown e gestire i casi in cui non c'e abbastanza spazio: un tooltip che finisce fuori dal viewport in alto o a sinistra deve essere riposizionato automaticamente.
CSS Anchor Positioning risolve questo con position-try-fallbacks, che
specifica una lista di posizionamenti alternativi che il browser testa in sequenza:
/* Definisci i posizionamenti alternativi */
@position-try --below {
top: calc(anchor(bottom) + 8px);
bottom: auto;
left: anchor(center);
right: auto;
}
@position-try --above {
top: auto;
bottom: calc(anchor(top) + 8px);
left: anchor(center);
right: auto;
}
@position-try --right {
top: anchor(center);
left: calc(anchor(right) + 8px);
right: auto;
bottom: auto;
}
@position-try --left {
top: anchor(center);
right: calc(anchor(left) + 8px);
left: auto;
bottom: auto;
}
.tooltip {
position: absolute;
position-anchor: --my-anchor;
/* Posizionamento default: sotto */
top: calc(anchor(bottom) + 8px);
left: anchor(center);
transform: translateX(-50%);
/* Fallback: prova prima sopra, poi destra, poi sinistra */
position-try-fallbacks: --above, --right, --left;
/* Fallback finale: usa la prima opzione disponibile nel viewport */
position-try-order: most-block-size;
}
Progressive Enhancement per Browser Senza Supporto
Per browser che non supportano ancora CSS Anchor Positioning (Firefox stabile
non lo supporta ancora all'inizio del 2026), usa @supports per
fornire un fallback:
/* Fallback: tooltip sempre visibile o con JS */
.tooltip {
/* Stili di default accessibili: mostro un title attribute */
display: none; /* nascosto, gestito da JS fallback */
}
/* Se il browser supporta anchor positioning: CSS puro */
@supports (anchor-name: --test) {
.trigger {
anchor-name: --my-anchor;
}
.tooltip {
display: block; /* visibile, gestito da CSS */
position: absolute;
position-anchor: --my-anchor;
top: calc(anchor(bottom) + 8px);
left: anchor(center);
transform: translateX(-50%);
/* Nascosto di default, mostrato su hover/focus */
opacity: 0;
pointer-events: none;
transition: opacity 0.15s;
}
.trigger:hover + .tooltip,
.trigger:focus + .tooltip {
opacity: 1;
pointer-events: auto;
}
}
/* JavaScript fallback per browser legacy */
if (!CSS.supports('anchor-name', '--test')) {
// Import libreria JS per tooltip
import('./tooltip-fallback.js').then(module => module.init());
}
Firefox: Supporto Ancora Limitato
All'inizio del 2026, Firefox non supporta ancora CSS Anchor Positioning nella
versione stabile (e in sviluppo attivo). Questo significa che il 20-25% degli
utenti desktop su Firefox vedra il fallback. Usa @supports per
assicurarti che l'esperienza sia sempre funzionale, anche senza anchor positioning.
Next Steps
Hai ora tooltip e dropdown declarativi in CSS puro. Il prossimo articolo della serie esplora la View Transitions API: come implementare animazioni fluide di navigazione native nel browser, sia per Single Page Applications che per Multi-Page Applications, senza librerie di terze parti.
Conclusioni
CSS Anchor Positioning e una delle aggiunte piu attese al linguaggio CSS degli ultimi anni. Elimina una categoria intera di codice JavaScript - il calcolo manuale delle coordinate di posizionamento - sostituendola con CSS dichiarativo che il browser gestisce nativamente, inclusi i fallback automatici e l'aggiornamento su scroll e resize.
Con supporto all'86% dei browser globali, puoi gia adottarla come enhancement progressivo, assicurandoti che i browser legacy abbiano comunque un'esperienza funzionale. La combinazione con la Popover API per la gestione dell'accessibilita rappresenta lo stack moderno e completo per la costruzione di UI overlay nel 2026.

Commenti
Caricamento commenti...
Accedi per commentare