prefers-reduced-motion: a volte meno movimento è più

La media query prefers-reduced-motion rileva se l'utente ha richiesto al sistema operativo di ridurre al minimo la quantità di animazioni o movimenti utilizzati.

Non a tutti piacciono le animazioni o le transizioni decorative e alcuni utenti soffrono di cinetosi quando si trovano di fronte a scorrimento parallasse, effetti di zoom e altro ancora. La query media delle preferenze dell'utente prefers-reduced-motion ti consente di progettare una variante del tuo sito con movimento ridotto per gli utenti che hanno espresso questa preferenza.

Browser Support

  • Chrome: 74.
  • Edge: 79.
  • Firefox: 63.
  • Safari: 10.1.

Source

Troppo movimento nella vita reale e sul web

L'altro giorno pattinavo sul ghiaccio con i miei figli. Era una bella giornata, il sole splendeva e la pista di pattinaggio era piena di gente ⛸. L'unico problema è che non sopporto la folla. Con così tanti obiettivi in movimento, non riesco a concentrarmi su nulla e mi ritrovo perso e con una sensazione di sovraccarico visivo completo, quasi come fissare un formicaio 🐜.

Folla di piedi di persone che pattinano sul ghiaccio.
Sovraccarico visivo nella vita reale.

A volte può succedere la stessa cosa sul web: con annunci lampeggianti, effetti di parallasse particolari, animazioni a sorpresa, video in riproduzione automatica e altro ancora, il web a volte può essere piuttosto opprimente… Fortunatamente, a differenza della vita reale, esiste una soluzione. La media query CSS prefers-reduced-motion consente agli sviluppatori di creare una variante di una pagina per gli utenti che preferiscono il movimento ridotto. Può trattarsi di qualsiasi cosa, dal non riprodurre automaticamente i video alla disattivazione di determinati effetti puramente decorativi, fino alla riprogettazione completa di una pagina per determinati utenti.

Prima di entrare nel dettaglio della funzionalità, facciamo un passo indietro e pensiamo a cosa servono le animazioni sul web. Se vuoi, puoi anche saltare le informazioni di base e passare direttamente ai dettagli tecnici.

Animazione sul web

L'animazione viene spesso utilizzata per fornire feedback all'utente, ad esempio per comunicare che un'azione è stata ricevuta ed è in fase di elaborazione. Ad esempio, su un sito web di shopping, un prodotto potrebbe essere animato per "volare" in un carrello virtuale, raffigurato come un'icona nell'angolo in alto a destra del sito.

Un altro caso d'uso prevede l'utilizzo del movimento per manipolare la percezione dell'utente utilizzando una combinazione di schermate scheletriche, metadati contestuali e anteprime di immagini di bassa qualità per occupare gran parte del tempo dell'utente e rendere l'intera esperienza più veloce. L'idea è di dare un contesto all'utente di ciò che sta per arrivare e nel frattempo caricare le cose il più rapidamente possibile.

Infine, ci sono effetti decorativi come gradienti animati, scorrimento parallasse, video di sfondo e molti altri. Anche se molti utenti apprezzano queste animazioni, alcuni non le gradiscono perché si sentono distratti o rallentati. Nel peggiore dei casi, gli utenti potrebbero persino soffrire di mal d'auto come se fosse un'esperienza reale, quindi per questi utenti la riduzione delle animazioni è una necessità medica.

Disturbo dello spettro vestibolare scatenato dal movimento

Alcuni utenti provano distrazione o nausea a causa dei contenuti animati. Ad esempio, le animazioni di scorrimento possono causare disturbi vestibolari quando gli elementi diversi da quello principale associato allo scorrimento si muovono molto. Ad esempio, le animazioni di scorrimento parallasse possono causare disturbi vestibolari perché gli elementi di sfondo si muovono a una velocità diversa rispetto agli elementi in primo piano. Le reazioni ai disturbi vestibolari (orecchio interno) includono vertigini, nausea ed emicrania e a volte richiedono riposo a letto per recuperare.

Rimuovere il movimento sui sistemi operativi

Molti sistemi operativi dispongono da tempo di impostazioni di accessibilità per specificare una preferenza per la riduzione del movimento. Gli screenshot seguenti mostrano la preferenza Riduci movimento di macOS Mojave e la preferenza Rimuovi animazioni di Android Pie. Se selezionate, queste preferenze fanno sì che il sistema operativo non utilizzi effetti decorativi come le animazioni di avvio delle app. Anche le applicazioni possono e devono rispettare questa impostazione e rimuovere tutte le animazioni non necessarie.

La schermata delle impostazioni di macOS con la casella di controllo "Riduci movimento" selezionata.
La schermata delle impostazioni di Android con la casella di controllo "Rimuovi le animazioni" selezionata.

Rimuovere il movimento sul web

Media Queries Level 5 porta anche sul web la preferenza utente per il movimento ridotto. Le media query consentono agli autori di testare ed eseguire query su valori o funzionalità dell'user agent o del dispositivo di visualizzazione indipendentemente dal documento di cui viene eseguito il rendering. La media query prefers-reduced-motion viene utilizzata per rilevare se l'utente ha impostato una preferenza del sistema operativo per ridurre al minimo la quantità di animazione o movimento utilizzato. Può assumere due valori possibili:

  • no-preference: indica che l'utente non ha espresso alcuna preferenza nel sistema operativo sottostante. Questo valore della parola chiave viene valutato come false nel contesto booleano.
  • reduce: indica che l'utente ha impostato una preferenza del sistema operativo che indica che le interfacce devono ridurre al minimo il movimento o l'animazione, preferibilmente al punto in cui tutti i movimenti non essenziali vengono rimossi.

Utilizzo della media query dai contesti CSS e JavaScript

Come per tutte le query supporti, prefers-reduced-motion può essere controllato da un contesto CSS e da un contesto JavaScript.

Per illustrare entrambi, supponiamo di avere un importante pulsante di registrazione su cui voglio che l'utente faccia clic. Potrei definire un'animazione "vibrazione" che attira l'attenzione, ma in quanto buon cittadino del web la riprodurrò solo per gli utenti che hanno esplicitamente acconsentito alle animazioni, ma non per tutti gli altri, ovvero gli utenti che hanno disattivato le animazioni o gli utenti che utilizzano browser che non comprendono la media query.

/*
  If the user has expressed their preference for
  reduced motion, then don't use animations on buttons.
*/
@media (prefers-reduced-motion: reduce) {
  button {
    animation: none;
  }
}

/*
  If the browser understands the media query and the user
  explicitly hasn't set a preference, then use animations on buttons.
*/
@media (prefers-reduced-motion: no-preference) {
  button {
    /* `vibrate` keyframes are defined elsewhere */
    animation: vibrate 0.3s linear infinite both;
  }
}

Per illustrare come utilizzare prefers-reduced-motion con JavaScript, immagina di aver definito un'animazione complessa con l'API Web Animations. Mentre le regole CSS vengono attivate dinamicamente dal browser quando le preferenze dell'utente cambiano, per le animazioni JavaScript devo rilevare personalmente le modifiche e poi interrompere manualmente le animazioni potenzialmente in corso (o riavviarle se l'utente me lo consente):

const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
mediaQuery.addEventListener('change', () => {
  console.log(mediaQuery.media, mediaQuery.matches);
  // Stop JavaScript-based animations.
});

Tieni presente che le parentesi intorno alla query supporti effettiva sono obbligatorie:

Cosa non fare
window.matchMedia('prefers-reduced-motion: reduce');
Cosa fare
window.matchMedia('(prefers-reduced-motion: reduce)');

Utilizzo della media query da <picture> contesti

Un caso d'uso interessante è quello di rendere la riproduzione di un AVIF, WebP o GIF animato dipendente dall'attributo media. Se (prefers-reduced-motion: no-preference) restituisce true, è sicuro visualizzare la versione animata, altrimenti la versione statica:

<picture>
  <!-- Animated versions. -->
  <source
    srcset="nyancat.avifs"
    type="image/avif"
    media="(prefers-reduced-motion: no-preference)"
  />
  <source
    srcset="nyancat.gif"
    type="image/gif"
    media="(prefers-reduced-motion: no-preference)"
  />
  <!-- Static versions. -->
  <img src="nyancat.png" alt="Nyan cat" width="250" height="250" />
</picture>

Puoi vedere l'esempio che segue. Prova ad attivare/disattivare le preferenze di movimento del dispositivo per notare la differenza.

Il famoso Nyan Cat.

Scoprire le preferenze dell'utente al momento della richiesta

L'intestazione dell'hint client Sec-CH-Prefers-Reduced-Motion consente ai siti di ottenere facoltativamente le preferenze di movimento dell'utente al momento della richiesta, consentendo ai server di incorporare il CSS corretto per motivi di rendimento.

Demo

Ho creato una piccola demo basata sulle fantastiche 🐈 HTTP Status Cats di Rogério Vicente. Innanzitutto, prenditi un momento per apprezzare la battuta, è esilarante e aspetterò. Ora che sei tornato, ti presento la demo. Quando scorri, ogni categoria di stato HTTP viene visualizzata alternativamente dal lato destro o sinistro. Si tratta di un'animazione a 60 FPS fluida, ma come accennato in precedenza, alcuni utenti potrebbero non apprezzarla o addirittura soffrire di cinetosi, quindi la demo è programmata per rispettare prefers-reduced-motion. Funziona anche in modo dinamico, quindi gli utenti possono modificare le proprie preferenze al volo, senza ricaricare la pagina. Se un utente preferisce un movimento ridotto, le animazioni di visualizzazione non necessarie vengono rimosse e rimane solo il movimento di scorrimento normale. Il seguente screencast mostra la demo in azione:

Video della prefers-reduced-motion demo app

Conclusioni

Il rispetto delle preferenze degli utenti è fondamentale per i siti web moderni e i browser espongono sempre più funzionalità per consentire agli sviluppatori web di farlo. Un altro esempio lanciato è prefers-color-scheme, che rileva se l'utente preferisce una combinazione di colori chiara o scura. Puoi leggere tutto su prefers-color-scheme nel mio articolo Hello Darkness, My Old Friend 🌒.

Il CSS Working Group sta standardizzando altre query dei media delle preferenze dell'utente, come prefers-reduced-transparency (rileva se l'utente preferisce una trasparenza ridotta), prefers-contrast (rileva se l'utente ha richiesto al sistema di aumentare o diminuire la quantità di contrasto tra colori adiacenti) e inverted-colors (rileva se l'utente preferisce i colori invertiti).

(Bonus) Forzare il movimento ridotto su tutti i siti web

Non tutti i siti utilizzano prefers-reduced-motion o forse non in modo significativo per i tuoi gusti. Se, per qualsiasi motivo, vuoi interrompere il movimento su tutti i siti web, puoi farlo. Un modo per farlo è inserire un foglio di stile con il seguente CSS in ogni pagina web che visiti. Esistono diverse estensioni del browser (da utilizzare a tuo rischio e pericolo) che lo consentono.

@media (prefers-reduced-motion: reduce) {
  *,
  ::before,
  ::after {
    animation-delay: -1ms !important;
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    background-attachment: initial !important;
    scroll-behavior: auto !important;
    transition-duration: 1ms !important;
    transition-delay: -1ms !important;
  }
}

Il CSS precedente esegue l'override delle durate di tutte le animazioni e transizioni in modo che siano così brevi da non essere più visibili. Poiché alcuni siti web dipendono dall'esecuzione di un'animazione per funzionare correttamente (forse perché un determinato passaggio dipende dall'attivazione dell'evento animationend), l'approccio più radicale animation: none !important; non funzionerebbe. Anche l'hack precedente non garantisce la riuscita su tutti i siti web (ad esempio, non può interrompere il movimento avviato utilizzando l'API Web Animations), quindi assicurati di disattivarlo quando noti un malfunzionamento.

Risorse

Ringraziamenti

Un ringraziamento speciale a Stephen McGruer, che ha implementato prefers-reduced-motion in Chrome e, insieme a Rob Dodson, ha anche esaminato questo documento.