Come le query dei contenitori, ma per query bloccate, scattate e con overflow.
Pubblicata: 15 gennaio 2025
Chrome 133 si basa sulle query dei contenitori introducendo le query dei contenitori dello stato di scorrimento. Ora è possibile eseguire query e adattamenti allo stato gestito dal browser per il posizionamento fisso, i punti di aggancio dello scorrimento e gli elementi scorrevoli da CSS.
Panoramica
Prima delle query sullo stato di scorrimento, devi utilizzare JavaScript per capire se un elemento è bloccato, agganciato o scorrevole. Ora esiste un metodo più efficace nel canale standard per conoscere queste informazioni e adattarsi di conseguenza. È disponibile anche un nuovo modo per attivare le animazioni, sbloccando l'animazione attivata dallo scorrimento dal CSS.
Ecco una panoramica delle query sullo stato disponibili a partire da Chrome 133:
- Stato bloccato:
- Attiva le modifiche dello stile quando un elemento è bloccato su un bordo.
- Stato a scatti:
- Attiva le modifiche dello stile quando un elemento viene agganciato a un asse.
- Stato scorrevole:
- Attiva le modifiche dello stile quando un elemento è in overflow.
La buona notizia è che tutto ciò che hai imparato dalle query dei contenitori ti aiuterà a utilizzare le query sullo stato di scorrimento.
Inoltre, non è stato ancora esplorato il territorio tra le animazioni basate sullo scorrimento e le query dei contenitori dello stato di scorrimento. Dobbiamo fare esperimenti con i tempi e il contesto per scoprire se è preferibile un'animazione basata sullo scorrimento o un'animazione dello stato di scorrimento attivata dallo scorrimento. Il video e la demo seguenti illustrano il problema: un'animazione attivata in modo fisso rispetto a un'animazione basata sullo scorrimento.
Prima query sullo stato di scorrimento
Il primo passaggio consiste nel definire il contenitore utilizzando un nuovo valore per la proprietà container-type
. Come per una query sul contenitore, l'elemento su cui vuoi eseguire la query è quello a cui assegni container-type
e, facoltativamente, un container-name
. Con le query sullo stato di scorrimento, specifichi l'elemento che è agganciato, bloccato o ha un overflow container-type: scroll-state
.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
}
Il secondo passaggio consiste nel selezionare l'elemento secondario del contenitore che risponderà allo stato, poiché con le query del contenitore non può essere lo stesso elemento che contiene container-type
.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
Il terzo passaggio consiste nel provarlo. Il seguente esempio di CSS applica lo stile rosso allo sfondo quando l'elemento .stuck-top
si attacca alla parte superiore in 0
. Con alcune righe aggiuntive al CSS che avremmo già scritto e un elemento contenitore aggiuntivo che esegue il proxy dello stato del browser, i nostri componenti sono molto più intelligenti rispetto all'ambiente circostante.
Potenziamento progressivo
La regola at @supports
e il relativo nidificazione ti consentono di aggiungere il miglioramento progressivo o l'utilizzo di funzionalità condizionali in appena un paio di righe di codice aggiuntive:
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
@supports (container-type: scroll-state) {
> nav {
@container scroll-state(stuck: top) {
background: Highlight;
color: HighlightText;
}
}
}
}
Inoltre, ricordati di utilizzare @media (prefers-reduced-motion: no-preference) {}
per i movimenti, se finisci per animare gli elementi della pagina con query sullo stato di scorrimento.
Casi d'uso
Persona bloccata
Forse questa sezione dovrebbe chiamarsi "situazioni complicate"? Si tratta di una piccola raccolta di casi d'uso relativi allo stato appiccicoso, oltre a una sezione bonus di idee da sviluppare.
@container scroll-state(stuck: top) {}
@container scroll-state(stuck: bottom) {}
Elenco completo della sintassi
Aggiungere un'ombra quando il veicolo è bloccato
Uno dei casi d'uso più comuni per una query bloccata riguarda le barre di navigazione che vogliono aggiungere box-shadow
quando sono bloccate, in modo da sembrare fluttuanti sopra i contenuti sovrapposti.
.stuck-top {
container-type: scroll-state;
position: sticky;
top: 0px;
> nav {
transition: box-shadow .3s ease;
@container scroll-state(stuck: top) {
box-shadow: var(--shadow-5);
}
}
}
Attiva l'intestazione bloccata corrente
Un altro scenario comune di feedback sull'interfaccia utente bloccata è l'evidenziazione dell'elemento attualmente bloccato. In un elenco di bande in ordine alfabetico, può essere molto utile e di supporto all'esperienza.
.sticky-slide {
dt {
container-type: scroll-state;
position: sticky;
inset-block-start: 0;
inset-inline: 0;
> header {
transition:
background .3s ease,
box-shadow .5s ease;
@container scroll-state(stuck: top) {
background: hsl(265 100% 27%);
box-shadow: 0 5px 5px #0003;
}
}
}
}
Ecco un'altra variante, in cui le intestazioni si trovano a lato degli elementi dell'elenco. Infinite possibilità.
Idea overflow
Ecco un elenco di demo in primo piano che potrebbero ispirarti ad aggiungere un po' di pepe alla demo o a rimuovere il relativo codice JavaScript con le query sullo stato di scorrimento. Ti consiglio di provare a crearne uno che ti piace, in modo da memorizzare la sintassi e le idee 😏.
- https://codepen.io/BlogFire/pen/PoGMjaX - variante di note adesive appiccicose
- https://codepen.io/mikegolus/pen/jOZzRzw: aggiungi ombre a una tabella quando sono fisse
- https://codepen.io/MarcRay/pen/PomBeP: la barra di navigazione sotto l'intestazione viene visualizzata all'attivazione
- https://codepen.io/kevinpowell/pen/OqKJjK - visualizzazione della barra di navigazione del piè di pagina
- https://codepen.io/abhisekz-the-decoder/pen/eKaLRd - intestazioni delle schede fisse
- https://codepen.io/tutsplus/pen/abojPjP - ombra dell'intestazione del prezzo all'attivazione
- https://codepen.io/kevinpowell/pen/KEjMEv: titoli della barra laterale delle sezioni fisse
Agganciato
Con le query sugli stati agganciati possiamo rimuovere parte della responsabilità da JavaScript e dagli eventi di aggancio e spostare la gestione nel CSS.
@container scroll-state(snapped: x) {}
@container scroll-state(snapped: y) {}
@container scroll-state(snapped: inline) {}
@container scroll-state(snapped: block) {}
Elenco completo della sintassi
Un piccolo promemoria, nel caso in cui tu abbia saltato la sezione Prima query sullo stato di scorrimento, il contenitore per una query di snap è l'elemento con scroll-snap-align
e l'elemento che può adattarsi deve essere un elemento secondario di quell'elemento. Ciò significa che sono necessari tre elementi per la configurazione:
a scroll container with `scroll-snap-type`
⤷ a snap target with both `scroll-snap-align` and `container-type: scroll-state`
⤷ a child of the snap target that can query the container for snap state
Metti in evidenza visivamente l'elemento agganciato
È molto comune, con uno scorrevole agganciato al centro, evidenziare o mettere in evidenza l'elemento agganciato al centro. In questo esempio di testimonianze, viene utilizzata la parola chiave not
, pertanto tutte le testimonianze non scattate hanno un'opacità ridotta, mentre quella scattata rimane nel suo stato di presentazione naturale.
.demo {
overflow: auto hidden;
scroll-snap-type: x mandatory;
> article {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
> * {
transition: opacity .5s ease;
@container not scroll-state(snapped: x) {
opacity: .25;
}
}
}
}
}
Mostra la didascalia dell'elemento agganciato
Questo è un buon esempio di come le query sullo stato di scorrimento attivano l'animazione attivata dallo scorrimento. È anche un buon esempio di quando rispettare il movimento ridotto è utile nel CSS.
.demo {
overflow-x: auto;
scroll-behavior-x: contain;
scroll-snap-type: x mandatory;
> .card {
container-type: scroll-state;
scroll-snap-align: center;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
figcaption {
transform: translateY(100%);
@container scroll-state(snapped: x) {
transform: translateY(0);
}
}
}
}
}
}
Animare gli elementi delle diapositive
È molto comune animare gli elementi di una presentazione o di una presentazione quando si tiene un discorso. In passato era piuttosto fastidioso scrivere un osservatore di intersezione per questo, che non faceva altro che impostare una classe sulla diapositiva. Ora non è necessario JavaScript.
html {
scroll-snap-type: y mandatory;
}
section {
container-type: scroll-state;
scroll-snap-align: start;
scroll-snap-stop: always;
@supports (container-type: scroll-state) {
@media (prefers-reduced-motion: no-preference) {
> h1 {
transition: opacity .5s ease, transform .5s var(--ease-spring-3);
transition-delay: .5s;
opacity: 0;
transform: scale(1.25);
@container scroll-state(snapped: block) {
opacity: 1;
transform: scale(1);
}
}
}
}
}
Potresti notare che tutte le query relative agli stati CSS agganciati si comportano come scrollsnapchanging
, anziché come scrollsnapchange
. In questo modo, hai a disposizione l'hook più precoce possibile per fornire un feedback visivo dell'elemento agganciato. Se è troppo avido, valuta l'evento JavaScript.
Scorrevole
La query sullo stato scorrevole sarà molto utile per mostrare le affordance visive per quando è possibile scorrere un'area di scorrimento. Prima delle query sullo stato di scorrimento, queste informazioni erano difficili da conoscere.
@container scroll-state(scrollable: top) {}
@container scroll-state(scrollable: right) {}
@container scroll-state(scrollable: bottom) {}
@container scroll-state(scrollable: left) {}
Elenco completo della sintassi
Indicare lo scorrimento con le ombre
Esiste un famoso trucco CSS di Lea Verou che utilizza background-attachment: local
per ottenere un effetto simile a questo, oltre a un modo per farlo con l'animazione basata sullo scorrimento. Ogni tecnica presenta dei compromessi, sta a noi capire quando e dove è più adatta.
L'esempio seguente utilizza un singolo elemento fisso che si estende per tutta la finestra di scorrimento. L'opacità di un gradiente in alto e di un gradiente in basso viene animata con @property
quando si applica la query sullo stato di scorrimento contestuale: @container scroll-state(scrollable: top)
.
Inoltre, è il primo contenitore che è sia un contenitore size
che scroll-state
.
.scroll-container {
container-type: scroll-state size;
overflow: auto;
&::after {
content: " ";
background: var(--_shadow-top), var(--_shadow-bottom);
transition:
--_scroll-shadow-color-1-opacity .5s ease,
--_scroll-shadow-color-2-opacity .5s ease;
@container scroll-state(scrollable: top) {
--_scroll-shadow-color-1-opacity: var(--_shadow-color-opacity, 25%);
}
@container scroll-state(scrollable: bottom) {
--_scroll-shadow-color-2-opacity: var(--_shadow-color-opacity, 25%);
}
}
}
Prompt freccia
A volte, mostrare una freccia può aiutare gli utenti a capire che un'area è scorrevole. Questi elementi tendono a indicare la direzione in cui può avvenire lo scorrimento e scompaiono quando non sono più necessari. Puoi farlo con il seguente codice.
@container scroll-state((scrollable: top) or (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
}
@container scroll-state((scrollable: top) and (not (scrollable: bottom))) {
translate: 0 calc(100% + 10px);
rotate: .5turn;
}
Torna all'inizio
Un'altra interazione con lo stato di scorrimento molto utilizzata è il pulsante di scorrimento fino in alto. Il seguente codice fa sì che il pulsante di scorrimento fino in alto scompaia quando non è possibile scorrere verso l'alto.
Questa soluzione è un po' invertita, ma ti consente di ridurre la quantità di CSS. La posizione di riposo naturale del pulsante è visibile, quindi devi dirgli di nascondersi quando non è più possibile scorrere verso l'alto.
@container not scroll-state(scrollable: top) {
translate: 0 calc(100% + 10px);
}
Studio continuo
Se cerchi altre informazioni, ecco alcune risorse che spaziano dai dettagli delle specifiche ad altri ottimi articoli che trattano questo argomento:
- Che altro dovremmo poter eseguire query sui contenitori? https://github.com/w3c/csswg-drafts/issues/5989
- scroll-state() explainer - https://drafts.csswg.org/css-conditional-5/scroll_state_explainer.md
- Specifica CSS scroll-state() - https://www.w3.org/TR/css-conditional-5/#scroll-state-container
- Istantanea del layout nel loop di eventi HTML
- Una puntata di un podcast sulle query sugli stati: https://nerdy.dev/the-css-podcast-on-state-queries
- Altri articoli
- https://utilitybend.com/blog/is-the-sticky-thing-stuck-is-the-snappy-item-snapped-a-look-at-state-queries-in-css/
- https://ishadeed.com/article/css-state-queries/
- https://csscade.com/can-you-detect-overflow-with-css/
- https://css-tip.com/overflow-detection/: rilevamento con animazione basata sullo scorrimento in un modo che non solo i bambini possono conoscere (con il compromesso della frode)