TL;DR
La proprietà CSS overscroll-behavior
consente agli sviluppatori di ignorare il comportamento predefinito di scorrimento dell'overflow del browser quando raggiungono la parte superiore o inferiore dei contenuti. I casi d'uso includono la disattivazione della funzionalità pull-to-refresh
su dispositivi mobili, la rimozione del bagliore dell'overscroll e degli effetti dell'effetto rubberbanding
e la possibilità di impedire lo scorrimento dei contenuti della pagina quando si trovano sotto un modale/overlay.
Contesto
Limiti e concatenamento degli scorrimenti
Lo scorrimento è uno dei modi più fondamentali per interagire con una pagina, ma alcuni pattern UX possono essere difficili da gestire a causa dei comportamenti predefiniti originali del browser. Ad esempio, analizziamo un riquadro a scomparsa delle app con un gran numero di elementi che l'utente potrebbe dover scorrere. Quando raggiungono la parte inferiore, il contenitore overflow smette di scorrere perché non ci sono altri contenuti da consumare. In altre parole, l'utente raggiunge un "confine di scorrimento". Nota però cosa succede se l'utente continua a scorrere. I contenuti dietro il riquadro a scomparsa iniziano a scorrere. Lo scorrimento viene rilevato dal contenitore principale; la pagina principale nell'esempio.
Questo comportamento si chiama scroll chain; il comportamento predefinito del browser quando scorrono i contenuti. Spesso l'impostazione predefinita è piacevole, ma a volte non è desiderabile e nemmeno inaspettata. Alcune app potrebbero voler fornire un'esperienza utente diversa quando l'utente raggiunge il limite di scorrimento.
Effetto pull-to-refresh
Il pull-to-refresh è un gesto intuitivo reso popolare dalle app mobile come Facebook e Twitter. Trascinando e rilasciando un feed social, si crea un nuovo spazio per il caricamento di post più recenti. Di fatto, questa particolare UX è diventata talmente popolare che anche i browser mobile come Chrome su Android hanno adottato lo stesso effetto. Se scorri verso il basso nella parte superiore della pagina, viene aggiornata l'intera pagina:
Per situazioni come la PWA di Twitter,
potrebbe avere senso disabilitare l'azione nativa di pull-to-refresh. Perché? In questa
app, probabilmente non vuoi che l'utente aggiorni accidentalmente la pagina. Inoltre, è possibile vedere un'animazione con doppio aggiornamento. In alternativa, potrebbe
essere più utile personalizzare l'azione del browser, allineandola meglio al branding
del sito. La parte sfortunata è che questo tipo di personalizzazione è
difficile da completare. Gli sviluppatori finiscono per scrivere codice JavaScript non necessario, aggiungere
ascoltatori touch non passivi (che bloccano lo scorrimento) o inserire l'intera pagina in un formato 100 vw/vh
<div>
(per evitare l'overflow della pagina). Queste soluzioni alternative hanno effetti negativi ben documentati sulle prestazioni di scorrimento.
Possiamo fare di meglio!
Ti presentiamo overscroll-behavior
La proprietà overscroll-behavior
è una nuova funzionalità CSS che controlla
il comportamento di ciò che accade quando scorri oltre un contenitore (compresa la pagina stessa). Puoi utilizzarla per annullare il concatenamento di scorrimento, disattivare/personalizzare l'azione pull-to-refresh, disattivare gli effetti del rubberbanding su iOS (quando Safari
implementa overscroll-behavior
) e altro ancora.
La parte migliore è che l'utilizzo di overscroll-behavior
non influisce negativamente sulle
prestazioni della pagina, come le violazioni menzionate nell'introduzione.
La proprietà assume tre possibili valori:
- auto: impostazione predefinita. Gli scorrimenti che hanno origine dall'elemento possono propagarsi agli elementi predecessori.
- contain: impedisce il concatenamento dello scorrimento. Gli scorrimenti non si propagano
ai predecessori, ma vengono mostrati gli effetti locali. Ad esempio, l'effetto di bagliore overscroll su Android o l'effetto elastico su iOS che avvisa l'utente quando raggiunge il limite di scorrimento. Nota: l'utilizzo di
overscroll-behavior: contain
sull'elementohtml
impedisce le azioni di navigazione overscroll. - none: uguale a
contain
ma impedisce anche gli effetti overscroll all'interno del nodo stesso (ad es. bagliore overscroll per Android o rubberbanding di iOS).
Analizziamo alcuni esempi per capire come utilizzare overscroll-behavior
.
Impedisci agli scorrimenti di uscire da un elemento con posizione fissa
Lo scenario del riquadro della chat
Considera l'uso di un riquadro della chat con posizione fissa che si trova in fondo alla pagina. L'obiettivo è che il riquadro della chat sia un componente autonomo e che scorra separatamente dai contenuti sottostanti. Tuttavia, a causa del concatenamento dello scorrimento, il documento inizia a scorrere non appena l'utente tocca l'ultimo messaggio nella cronologia chat.
Per questa app, è più appropriato che gli scorrimenti provenienti all'interno
della chat rimangano all'interno della chat. Possiamo farlo aggiungendo overscroll-behavior: contain
all'elemento che contiene i messaggi di chat:
#chat .msgs {
overflow: auto;
overscroll-behavior: contain;
height: 300px;
}
In sostanza, stiamo creando una separazione logica tra il contesto a scorrimento del riquadro della chat e la pagina principale. Il risultato finale è che la pagina principale rimane in posizione quando l'utente raggiunge la parte superiore o inferiore della cronologia chat. Gli scorrimenti che iniziano nella chatbox non si propagano.
Scenario overlay di pagina
Un'altra variante dello scenario "underscroll" è quando vedi contenuti che scorrono dietro un overlay in posizione fissa. Un gioco d'azzardo
overscroll-behavior
è in regola! Il browser sta cercando di essere utile,
ma alla fine il sito sembra pieno di errori.
Esempio - modale con e senza overscroll-behavior: contain
:
Disabilitazione del pull-to-refresh
La disattivazione dell'azione pull-to-refresh utilizza una singola riga di CSS. Basta evitare il concatenamento
dell'intero elemento che definisce l'area visibile. Nella maggior parte dei casi, si tratta di
<html>
o <body>
:
body {
/* Disables pull-to-refresh but allows overscroll glow effects. */
overscroll-behavior-y: contain;
}
Con questa semplice aggiunta, correggiamo le animazioni di doppio pull-to-refresh nella demo della chatbox e possiamo implementare un effetto personalizzato che utilizza un'animazione di caricamento più ordinata. Inoltre, con l'aggiornamento, l'intera casella di posta si sfoca:
Ecco uno snippet del codice completo:
<style>
body.refreshing #inbox {
filter: blur(1px);
touch-action: none; /* prevent scrolling */
}
body.refreshing .refresher {
transform: translate3d(0,150%,0) scale(1);
z-index: 1;
}
.refresher {
--refresh-width: 55px;
pointer-events: none;
width: var(--refresh-width);
height: var(--refresh-width);
border-radius: 50%;
position: absolute;
transition: all 300ms cubic-bezier(0,0,0.2,1);
will-change: transform, opacity;
...
}
</style>
<div class="refresher">
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
<div class="loading-bar"></div>
</div>
<section id="inbox"><!-- msgs --></section>
<script>
let _startY;
const inbox = document.querySelector('#inbox');
inbox.addEventListener('touchstart', e => {
_startY = e.touches[0].pageY;
}, {passive: true});
inbox.addEventListener('touchmove', e => {
const y = e.touches[0].pageY;
// Activate custom pull-to-refresh effects when at the top of the container
// and user is scrolling up.
if (document.scrollingElement.scrollTop === 0 && y > _startY &&
!document.body.classList.contains('refreshing')) {
// refresh inbox.
}
}, {passive: true});
</script>
Disattivazione degli effetti overscroll e rubberbanding
Per disattivare l'effetto di rimbalzo quando raggiungi un limite di scorrimento, utilizza
overscroll-behavior-y: none
:
body {
/* Disables pull-to-refresh and overscroll glow effect.
Still keeps swipe navigations. */
overscroll-behavior-y: none;
}
Demo completa
Combinando tutto, la demo della chatbox completa utilizza overscroll-behavior
per creare un'animazione pull-to-refresh personalizzata e impedire agli scorrimenti di uscire dal widget della chatbox. Ciò fornisce un'esperienza utente
ottimale, che sarebbe stata difficile da ottenere senza il CSS
overscroll-behavior
.