24 settembre 2026
State queries in CSS nel 2025: UI reattive senza JavaScript
Dalle scroll state queries alle anchored container queries: nuovi strumenti per reagire allo stato reale dei componenti, in modo dichiarativo e performante.
Le container queries hanno cambiato il modo di costruire componenti riusabili. Nel 2025 si spingono oltre con le state queries: puoi applicare stili quando un elemento è sticky e “stuck”, quando uno slide è snapped, o quando un contenitore è davvero scrollabile—in CSS, senza listener e calcoli. In più, si intravede un futuro interessante con le anchored container queries per adattare tooltip e popover ai fallback di anchor positioning.
Perché le state queries sono il passo successivo
Per anni abbiamo fatto responsive design quasi esclusivamente con media queries, che però “vedono” solo il viewport (e poche preferenze globali come il color scheme). Questo porta a un compromesso strutturale: decisioni di layout a livello pagina che finiscono per governare anche i componenti, rendendoli meno autonomi e riusabili.
Le container queries hanno sbloccato un cambio di paradigma: un componente può adattarsi al contesto in cui vive, interrogando il contenitore invece dello schermo.
Nel 2025 questa direzione diventa ancora più interessante: oltre a “quanto è grande” un contenitore o “che variabile CSS ha”, possiamo chiedere anche in che stato si trova. È qui che entrano in gioco le state queries.
In pratica: molti pattern UI che prima richiedevano JavaScript (listener di scroll, misurazioni, throttling/debouncing, gestione stati) diventano dichiarativi in CSS.
Ripasso: container queries (la base)
Per abilitare una query su un contenitore, lo si dichiara come container con container-type, poi si usano regole @container per applicare stili condizionati.
- Size queries: stili in base alle dimensioni del contenitore. Sono ormai ampiamente disponibili.
- Style queries: stili in base al valore di una custom property (supporto non uniforme in tutti i browser).
Le novità più “UI-driven” arrivano ora con le state-based queries.
Scroll state queries: CSS che reagisce allo scroll (davvero)
Le prime state queries ad arrivare in modo concreto sono le scroll state queries (in Chrome dalla 133). L’idea è semplice: dichiarare un contenitore come “osservabile” rispetto a certi stati di scroll e poi interrogare tali stati da CSS.
Per usarle si imposta sul genitore:
.wrapper {
container-type: scroll-state;
}
Da lì si possono scrivere query che reagiscono a tre stati principali:
stucksnappedscrollable
Nota: spesso non serve nemmeno incapsulare queste regole in
@supports. I browser che non riconosconocontainer-type: scroll-stateignorano semplicemente la dichiarazione, e le query collegate non avranno effetto.
1) stuck: quando lo sticky è “attaccato” a un bordo
Se usi position: sticky, finora lo styling “quando è davvero sticky” era tipicamente demandato a JS (o a soluzioni fragili). Con stuck puoi cambiare stile quando l’elemento è bloccato su un edge.
Esempio tipico: header che diventa opaco quando si attacca in alto.
.layout {
container-type: scroll-state;
}
.header {
position: sticky;
top: 0;
background: transparent;
transition: background 200ms ease;
}
@container scroll-state(stuck: top) {
.header {
background: color-mix(in oklab, black 70%, transparent);
backdrop-filter: blur(8px);
}
}
Oltre a top/bottom, puoi usare anche valori logici (es. inline-start, inline-end) per supportare layout RTL e scrittura verticale in modo più robusto.
Use case reali:
- intestazioni di sezione in liste (rubrica, indice alfabetico) che cambiano stile solo quando sono effettivamente “in sticky”;
- micro-animazioni “triggerate” dallo stato sticky senza usare scroll event.
2) snapped: quando un elemento è lo snap attivo
Se costruisci caroselli o scroller a snap, spesso vuoi evidenziare l’elemento “centrato”/attivo: scala, opacità, caption, progress, ecc.
Con snapped puoi applicare stili quando un item è snap-pato su un asse.
.scroller {
container-type: scroll-state;
overflow: auto;
scroll-snap-type: x mandatory;
}
.item {
scroll-snap-align: center;
transform: scale(.8);
transition: transform 200ms ease;
}
@container scroll-state(snapped: inline) {
.item {
transform: scale(1);
}
}
Valori utili: x, y, oppure inline/block.
Use case reali:
- evidenziare lo slide attivo;
- mostrare/nascondere caption o dettagli solo sull’item snapped;
- introdurre pattern “scrollytelling” basati su snapping.
Extra: esistono anche eventi JS legati allo snapping (es. per analytics o sound design), ma lo styling “attivo/non attivo” può restare in CSS.
3) scrollable: quando c’è overflow (e in quale direzione)
Questo stato è perfetto per i segnali visivi: ombre, gradienti, frecce, “back to top”, indicatori che compaiono solo se c’è davvero contenuto da scorrere.
Esempio concettuale: mostra un’ombra a destra se si può scrollare verso destra.
.panel {
container-type: scroll-state;
overflow: auto;
}
@container scroll-state(scrollable: right) {
.panel {
box-shadow: inset -16px 0 16px -16px rgba(0,0,0,.35);
}
}
Anche qui sono disponibili direzioni fisiche (top/right/bottom/left) e logiche.
Use case reali:
- “scroll hint” su dispositivi con scrollbar overlay (dove l’overflow non è evidente);
- frecce nei caroselli che scompaiono automaticamente quando si raggiunge il bordo;
- link “torna su” che appare solo se è possibile scrollare verso l’alto.
Importante:
scrollableindica che lo scroll è possibile in quella direzione, non che l’utente stia scrollando attivamente in quel momento.
Anchored container queries: styling in base al fallback di anchor positioning (in arrivo)
Chi usa CSS anchor positioning sa che tooltip e popover spesso devono “flipparsi” (sopra/sotto, sinistra/destra) in base allo spazio disponibile. Con position-try e i fallback puoi cambiare posizione in modo robusto.
Il pezzo che mancava, però, era poter fare styling diverso a seconda del fallback effettivamente scelto.
Esempio classico: la freccetta del tooltip (il triangolino) deve spostarsi e invertire i bordi quando il popover passa da sopra a sotto l’anchor.
Le anchored container queries introducono un container-type dedicato e la possibilità di interrogare il fallback attivo (es. flip-block, o fallback custom nominati). È una leva enorme per rifinire popover/tooltip senza gestire manualmente classi e stati via JS.
Al momento è una funzionalità in evoluzione e sperimentale, ma la direzione è chiara: lo stato “di layout” scelto dal motore diventa interrogabile in CSS.
Implicazione pratica: meno JS “di contorno”, più componenti autonomi
Le state queries non sono un gadget: spostano in CSS una categoria intera di logiche che prima richiedeva JavaScript per capire cosa sta succedendo (sticky attivo, slide snapped, overflow disponibile, posizione effettiva di un popover).
In sintesi
- Container queries hanno reso i componenti davvero contestuali.
- Le scroll state queries aggiungono reattività “di stato” con
stuck,snapped,scrollable. - Le anchored container queries promettono di completare il quadro per tooltip/popover anchor-based.
Se costruisci design system o UI componentizzate, il consiglio operativo è semplice: inizia a trattare questi stati come parte del contract del componente. Quando lo stato è interrogabile in CSS, lo styling diventa più prevedibile, testabile e spesso anche più performante—con meno codice imperativo da mantenere.