A consulta de mídia "prefers-reduced-motion" detecta se o usuário solicitou que o sistema operacional minimize a quantidade de animação ou movimento usado.
Nem todo mundo gosta de animações decorativas ou transições, e alguns usuários podem sentir enjoo
de movimento ao se depararem com rolagem de paralaxe, efeitos de zoom e muito mais. A consulta de mídia de preferência do usuário
prefers-reduced-motion
permite projetar uma variante com movimento reduzido do seu site para usuários que
expressaram essa preferência.
Muito movimento na vida real e na Web
Outro dia, eu estava patinando no gelo com meus filhos. Estava um dia lindo, o sol estava brilhando, e a pista de gelo estava lotada de gente ⛸. O único problema com isso: eu não lido bem com multidões. Com tantos alvos em movimento, não consigo me concentrar em nada e acabo me sentindo perdida e com uma sensação de sobrecarga visual completa, quase como olhar para um formigueiro 🐜.
Às vezes, o mesmo pode acontecer na Web: com anúncios intermitentes, efeitos de paralaxe sofisticados, animações de revelação surpreendentes, vídeos que são reproduzidos automaticamente e muito mais, a Web às vezes pode ser bastante cansativa.
Felizmente, ao contrário da vida real, há uma solução para isso. A consulta de mídia CSS
prefers-reduced-motion
permite que os desenvolvedores criem uma variante de uma página para usuários que preferem
movimentos reduzidos. Isso pode ser desde evitar a reprodução automática de vídeos até
desativar alguns efeitos puramente decorativos ou redesenhar completamente uma página para determinados usuários.
Antes de entrar no recurso, vamos dar um passo atrás e pensar em como as animações são usadas na Web. Se quiser, você também pode pular as informações de contexto e ir direto para os detalhes técnicos.
Animação na Web
Muitas vezes, a animação é usada para fornecer feedback ao usuário, por exemplo, para informar que uma ação foi recebida e está sendo processada. Por exemplo, em um site de compras, um produto pode ser animado para "voar" para um carrinho de compras virtual, representado como um ícone no canto superior direito do site.
Outro caso de uso envolve o uso de movimento para hackear a percepção do usuário usando uma mistura de telas esqueleto, metadados contextuais e visualizações de imagens de baixa qualidade para ocupar muito do tempo do usuário e fazer com que toda a experiência pareça mais rápida. A ideia é dar contexto ao usuário sobre o que está por vir e, ao mesmo tempo, carregar as coisas o mais rápido possível.
Por fim, há efeitos decorativos, como gradientes animados, rolagem paralaxe, vídeos de plano de fundo e vários outros. Embora muitas pessoas gostem dessas animações, algumas não gostam delas porque se sentem distraídos ou lentos. Na pior das hipóteses, os usuários podem até sofrer de enjoo como se fosse uma experiência real. Portanto, para esses usuários, reduzir animações é uma necessidade médica.
Distúrbio do espectro vestibular acionado por movimento
Alguns usuários sentem distração ou náusea devido a conteúdo animado. Por exemplo, animações de rolagem podem causar distúrbios vestibulares quando elementos diferentes do principal associado à rolagem se movem muito. Por exemplo, animações de rolagem de paralaxe podem causar distúrbios vestibulares porque os elementos de segundo plano se movem em uma taxa diferente dos elementos de primeiro plano. As reações de distúrbios vestibulares (do ouvido interno) incluem tontura, náusea e enxaqueca, e às vezes exigem repouso para se recuperar.
Remover o movimento em sistemas operacionais
Muitos sistemas operacionais têm configurações de acessibilidade para especificar uma preferência por movimento reduzido por muito tempo. As capturas de tela a seguir mostram a preferência Reduzir movimento do macOS Mojave e a preferência Remover animações do Android Pie. Quando marcadas, essas preferências fazem com que o sistema operacional não use efeitos decorativos, como animações de inicialização de apps. Os próprios apps podem e devem respeitar essa configuração e remover todas as animações desnecessárias.
Remover movimento na Web
O Media Queries Level 5 também traz a preferência do usuário
de movimento reduzido para a Web. As consultas de mídia permitem que os autores testem e consultem valores ou recursos
do agente do usuário ou do dispositivo de exibição, independentemente do documento renderizado. A consulta de mídia
prefers-reduced-motion
é usada
para detectar se o usuário definiu uma preferência do sistema operacional para minimizar a quantidade de animação ou
movimento que ele usa. Ele pode ter dois valores possíveis:
no-preference
: indica que o usuário não fez nenhuma preferência no sistema operacional subjacente. Esse valor de palavra-chave é avaliado comofalse
no contexto booleano.reduce
: indica que o usuário definiu uma preferência do sistema operacional indicando que as interfaces precisam minimizar o movimento ou a animação, de preferência até o ponto em que todos os movimentos não essenciais são removidos.
Como trabalhar com a consulta de mídia em contextos de CSS e JavaScript
Assim como em todas as consultas de mídia, prefers-reduced-motion
pode ser verificado em um contexto CSS e em
JavaScript.
Para ilustrar os dois, suponha que eu tenha um botão de inscrição importante em que quero que o usuário clique. Eu poderia definir uma animação de "vibração" que chama a atenção, mas, como um bom cidadão da Web, só a mostro para usuários que aceitam explicitamente animações, mas não para todos, que podem ser usuários que desativaram animações ou usuários em navegadores que não entendem a consulta de mídia.
/*
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;
}
}
Para ilustrar como trabalhar com prefers-reduced-motion
com JavaScript, imagine que eu tenha
definido uma animação complexa com a
API Web Animations. Embora as regras de CSS
sejam acionadas dinamicamente pelo navegador quando a preferência do usuário muda, para animações
JavaScript, preciso detectar as mudanças e interromper manualmente as animações
que estão em andamento (ou reiniciá-las se o usuário permitir):
const mediaQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
mediaQuery.addEventListener('change', () => {
console.log(mediaQuery.media, mediaQuery.matches);
// Stop JavaScript-based animations.
});
Os parênteses ao redor da consulta de mídia real são obrigatórios:
window.matchMedia('prefers-reduced-motion: reduce');
window.matchMedia('(prefers-reduced-motion: reduce)');
Como trabalhar com a consulta de mídia de contextos <picture>
Um caso de uso interessante é fazer com que a reprodução de um AVIF, WebP ou GIF animado dependa do
atributo media
. Se (prefers-reduced-motion: no-preference)
for avaliado como true
, será possível
exibir a versão animada. Caso contrário, a versão estática será mostrada:
<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>
Confira o exemplo a seguir. Tente ativar as preferências de movimento do dispositivo para notar a diferença.
Descobrir as preferências do usuário no momento da solicitação
O cabeçalho de sugestão de cliente Sec-CH-Prefers-Reduced-Motion
permite que os sites recebam as preferências de movimento do usuário opcionalmente no momento da solicitação,
permitindo que os servidores inlinem o CSS correto por motivos de performance.
Demonstração
Criei uma pequena demonstração com base nos incríveis
gatos de status HTTP 🐈 de Rogério Vicente. Primeiro, aproveite a piada, ela é
hilária, e eu vou esperar. Agora que você voltou, vou apresentar a
demonstração. Quando você rola, cada categoria de status HTTP aparece alternadamente no lado direito ou esquerdo. É uma animação de 60 QPS suave,
mas, como descrito anteriormente, alguns usuários podem não gostar dela ou até mesmo ficar com enjoo do movimento. Por isso, a
demonstração é programada para respeitar prefers-reduced-motion
. Isso funciona de forma dinâmica, para que os usuários possam
mudar a preferência rapidamente, sem precisar recarregar. Se um usuário preferir um movimento reduzido, as
animações de revelação desnecessárias serão removidas, e apenas o movimento de rolagem normal será mantido. O
screencast a seguir mostra a demonstração em ação:
Conclusões
Respeitar as preferências do usuário é fundamental para os sites modernos, e os navegadores estão expondo cada vez mais
recursos para que os desenvolvedores Web possam fazer isso. Outro exemplo lançado é o
prefers-color-scheme
, que
detecta se o usuário prefere um esquema de cores claro ou escuro. Leia tudo sobre
prefers-color-scheme
no meu artigo Hello Darkness, My Old Friend 🌒.
O Grupo de Trabalho do CSS está padronizando mais
consultas de mídia de preferência do usuário, como
prefers-reduced-transparency
(detecta se o usuário prefere transparência reduzida),
prefers-contrast
(detecta se o usuário
pediu para o sistema aumentar ou diminuir a quantidade de contraste entre cores adjacentes)
e inverted-colors
(detecta se o usuário
prefere cores invertidas).
(Bônus) Forçar o movimento reduzido em todos os sites
Nem todos os sites usam prefers-reduced-motion
ou talvez não o suficiente para você.
Se, por algum motivo, você quiser desativar a animação em todos os sites, é possível fazer isso. Uma maneira de fazer
isso é injetar uma folha de estilo com o CSS abaixo em todas as páginas da Web que você visitar. Existem várias extensões de navegador que permitem isso (use por sua conta e risco).
@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;
}
}
O CSS anterior substitui as durações de todas as animações e transições
para um tempo tão curto que elas não são mais perceptíveis. Como alguns sites dependem de uma animação
para funcionar corretamente (talvez porque uma determinada etapa depende do disparo do
evento animationend
),
a abordagem mais radical de animation: none !important;
não funciona. Mesmo o hack anterior não tem
garantia de sucesso em todos os sites (por exemplo, ele não pode interromper o movimento iniciado usando a
API Web Animations). Portanto, desative-o
quando notar uma falha.
Links relacionados
- Rascunho mais recente do editor da especificação Media Queries Level 5.
prefers-reduced-motion
em Status da plataforma do Chrome.prefers-reduced-motion
Bug do Chromium.- Piscar Intent to Implement posting.
Agradecimentos
Um agradecimento a Stephen McGruer, que implementou a
prefers-reduced-motion
no Chrome e, junto com
Rob Dodson, também analisou este documento.
Imagem principal de Hannah Cauhepe no Unsplash.