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

La query multimediale prefers-Reduced motion rileva se l'utente ha richiesto al sistema operativo di ridurre al minimo la quantità di animazione o movimento utilizzato.

Non a tutti piacciono le transizioni o le animazioni decorative e alcuni utenti provano addirittura il mal di movimento quando si trovano di fronte allo scorrimento con parallasse, agli effetti di zoom e altro ancora. La query multimediale prefers-reduced-motion per le preferenze utente ti consente di progettare una variante del tuo sito con minore movimento per gli utenti che hanno espresso questa preferenza.

Supporto dei browser

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

Origine

Troppo movimento nella vita reale e sul web

L'altro giorno pattinavo con i miei figli. Era una bella giornata, il sole splendeva e la pista di ghiaccio era piena di gente ⛸. L'unico problema: non so gestire bene la folla. Con così molti obiettivi in movimento, non riesco a concentrarmi su nulla e finisco per sentirmi perso e con una sensazione di completo sovraccarico visivo, quasi come se guardassi una formicaio 🐜.

Una folla di persone che pattinano sul ghiaccio.
Sovraccarico visivo nella vita reale.

A volte può succedere lo stesso sul web: con annunci lampeggianti, effetti di parallasse elaborati, animazioni di rivelazione sorprendenti, video con riproduzione automatica e altro ancora, a volte il web può essere piuttosto opprimente… Fortunatamente, a differenza della vita reale, esiste una soluzione. La query multimediale 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, dall'evitare la riproduzione automatica dei video alla disattivazione di determinati effetti puramente decorativi, fino alla riprogettazione completa di una pagina per determinati utenti.

Prima di approfondire la funzionalità, facciamo un passo indietro e pensiamo a cosa si usano le animazioni sul web. Se vuoi, puoi anche saltare le informazioni di base e passare direttamente ai dettagli tecnici.

Animazione sul web

Le animazioni vengono spesso utilizzate per fornire feedback all'utente, ad esempio per comunicargli che un'azione è stata ricevuta ed è in corso di elaborazione. Ad esempio, su un sito web di shopping, un prodotto potrebbe essere animato in modo da "volare" in un carrello virtuale, rappresentato 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 tramite una combinazione di schermate di scheletro, metadati contestuali e anteprime di immagini di bassa qualità per occupare molto tempo dell'utente e far sembrare più veloce l'intera esperienza. L'idea è fornire all'utente il contesto di ciò che sta per accadere e nel frattempo caricare le informazioni il più rapidamente possibile.

Infine, ci sono gli effetti decorativi, come gradienti animati, scorrimento parallattico, video in background e molti altri. Sebbene molte persone apprezzino queste animazioni, alcune non le amano perché si sentono distratte o rallentate. Nel peggiore dei casi, gli utenti potrebbero persino soffrire di cinetosi come se si trattasse di un'esperienza reale, quindi per questi utenti la riduzione delle animazioni è una necessità medica.

Disturbo dello spettro vestibolare attivato dal movimento

Alcuni utenti avvertono distrazione o nausea a causa dei contenuti animati. Ad esempio, le animazioni con scorrimento possono causare disturbi vestibolari quando elementi diversi dall'elemento principale associato allo scorrimento si spostano molto. Ad esempio, le animazioni con 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 relative a disturbi vestibolari (dell'orecchio interno) includono vertigini, nausea e emicrania e a volte richiedono il riposo a letto per il recupero.

Rimuovere il movimento sui sistemi operativi

Molti sistemi operativi dispongono da tempo di impostazioni di accessibilità per specificare una preferenza per il movimento ridotto. Gli screenshot seguenti mostrano l'opzione Riduci movimento di macOS Mojave e l'opzione Rimuovi animazioni di Android Pie. Se selezionate, queste preferenze impediscono al sistema operativo di utilizzare effetti decorativi come le animazioni di avvio delle app. Anche le applicazioni stesse 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 animazioni" selezionata.

Rimuovi il movimento sul web

Il livello 5 delle query sui media consente di applicare la preferenza dell'utente per le animazioni ridotte anche al web. Le query sui media consentono agli autori di testare e eseguire query sui valori o sulle funzionalità dell'agente utente o del dispositivo di visualizzazione indipendentemente dal documento visualizzato. La query media 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 utilizzata. Possono avere due valori possibili:

  • no-preference: indica che l'utente non ha impostato alcuna preferenza nel sistema operativo di base. Il valore di questa 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 fino a quando non viene rimosso tutto il movimento non essenziale.

Lavorare con la query multimediale da contesti CSS e JavaScript

Come per tutte le query sui media, 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 "vibrante" che attira l'attenzione, ma da buon cittadino del web la mostrerò solo agli utenti che accettano esplicitamente le animazioni, ma non a tutti gli altri, ad esempio agli utenti che hanno disattivato le animazioni o a quelli che utilizzano browser che non comprendono la query sui media.

/*
  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 delle animazioni web. Mentre le regole CSS vengono attivate dinamicamente dal browser quando le preferenze dell'utente cambiano, per le animazioni JavaScript devo rilevare le modifiche autonomamente e interrompere manualmente le animazioni potenzialmente in esecuzione (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 che circondano la query sui contenuti multimediali effettiva sono obbligatorie:

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

Utilizzo della query sui contenuti multimediali dai contesti <picture>

Un caso d'uso interessante è quello di far dipendere la riproduzione di un file AVIF, WebP o GIF animato dall'attributo media. Se (prefers-reduced-motion: no-preference) ha il valore true, è possibile 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 seguente. Prova a disattivare e riattivare le preferenze relative al movimento del dispositivo per vedere la differenza.

Il famoso Nyan Cat.

Scoprire le preferenze dell'utente al momento della richiesta

L'intestazione dell'indicazione 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 inserire in linea il CSS corretto per motivi di prestazioni.

Demo

Ho creato una piccola demo basata sui fantastici 🐈 gatti di stato HTTP di Rogério Vicente. Prima di tutto, dedica un momento ad apprezzare la battuta, è esilarante e ti aspetto. Ora che sei tornato, ti presento la demo. Quando scorri, ogni stato HTTP viene visualizzato alternativamente sul lato destro o sinistro. Si tratta di un'animazione fluida a 60 FPS, ma come indicato in precedenza, alcuni utenti potrebbero non apprezzarla o addirittura soffrire di cinetosi, pertanto la demo è programmata per rispettare prefers-reduced-motion. Questo funziona anche in modo dinamico, quindi gli utenti possono modificare le preferenze all'istante, senza necessità di ricarica. Se un utente preferisce ridurre il movimento, 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 demo dell'app prefers-reduced-motion

Conclusioni

Il rispetto delle preferenze degli utenti è fondamentale per i siti web moderni e i browser stanno esponendo 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 gruppo di lavoro CSS sta standardizzando altre query sui contenuti multimediali per le 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 i colori adiacenti) e inverted-colors (rileva se l'utente preferisce i colori invertiti).

(Extra) Imposizione del movimento ridotto su tutti i siti web

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

@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;
  }
}

Questo meccanismo è dovuto al fatto che il codice CSS precedente sostituisce la durata di tutte le animazioni e le transizioni a un tempo così breve da non essere più percettibile. Poiché alcuni siti web dipendono da un'animazione da eseguire per poter 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 il funzionamento 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.

Ringraziamenti

Un grande ringraziamento a Stephen McGruer che ha implementato prefers-reduced-motion in Chrome e, insieme a Rob Dodson, ha anche esaminato questo documento. Immagine hero di Hannah Cauhepe su Unsplash.