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 ou transições decorativas, e alguns usuários sentem enjoo
de movimento ao se deparar com paralaxe, efeitos de zoom etc. A consulta de mídia de preferência do usuário
prefers-reduced-motion
permite criar uma variante de redução de movimento 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. Era um dia lindo, com sol brilhando, e a pista de patinação estava lotada de pessoas ⛸. O único problema: não me adapto bem à multidão. Com tantos alvos em movimento, eu não consigo me concentrar em nada e acabo perdida e com uma sensação de sobrecarga visual completa, quase como olhar para um formigueiro 🐜.
![Multidão de pés de pessoas patinando no gelo.](https://web.dev/static/articles/prefers-reduced-motion/image/throng-feet-ice-skating-57c271f1a5c82.jpg?authuser=6&hl=pt)
Às vezes, o mesmo pode acontecer na Web: com anúncios que piscam, efeitos de paralaxe extravagantes, animações de revelação surpreendentes, vídeos com reprodução automática e assim por diante, a Web às vezes pode ficar sobrecarregado...
Felizmente, diferentemente 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
movimento reduzido. Isso pode incluir desde evitar a reprodução automática de vídeos, desativar alguns efeitos puramente decorativos até recriar completamente uma página para determinados usuários.
Antes de abordar o recurso, vamos pensar sobre para que as animações são usadas na Web. Se quiser, você também pode pular as informações básicas e passar direto para os detalhes técnicos abaixo.
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 poderia ser animado para "voar" em 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 combinação de telas esqueleto, metadados contextuais e visualizações de imagens de baixa qualidade para ocupar muito 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 tudo o mais rápido possível.
Por fim, há efeitos decorativos, como gradientes animados, rolagem paralaxe, vídeos em segundo plano e muitos outros. Embora muitos usuários gostem dessas animações, outros não gostam delas porque se sentem distraídas ou desaceleradas. Na pior das hipóteses, os usuários podem até sofrer de enjoo como se fosse uma experiência da vida real. Portanto, para eles, reduzir as 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, as animações de rolagem podem causar distúrbios vestibulares quando elementos diferentes do principal associado à rolagem se movem muito. Por exemplo, as animações de rolagem paralaxe podem causar distúrbios vestibulares porque os elementos de fundo se movem em uma taxa diferente dos elementos de primeiro plano. As reações vestibulares (ouvido interno) incluem tontura, náusea e enxaqueca, e, às vezes, exigem repouso na cama para se recuperar.
Remover movimento nos 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 abaixo mostram a preferência Reduzir movimento do macOS Mojave e 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 aplicativos também podem e precisam respeitar essa configuração e remover todas as animações desnecessárias.
![Captura da tela de configurações do macOS com a caixa de seleção "Reduzir movimento" marcada.](https://web.dev/static/articles/prefers-reduced-motion/image/a-screenshot-the-macos-s-02f7529755e96.png?authuser=6&hl=pt)
![Uma captura de tela da tela de configurações do Android com a caixa de seleção "Remover animações" marcada.](https://web.dev/static/articles/prefers-reduced-motion/image/a-screenshot-the-android-94061601243dd.png?authuser=6&hl=pt)
Remover movimento na Web
As consultas de mídia de nível 5 também trazem 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 user agent ou do dispositivo de exibição independente do documento que está sendo 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 usado. Pode usar dois valores possíveis:
no-preference
: indica que o usuário não deu 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 de sistema operacional indicando que as interfaces precisam minimizar o movimento ou a animação, de preferência ao ponto em que todos os movimentos não essenciais são removidos.
Como trabalhar com a consulta de mídia de contextos CSS e JavaScript
Como em todas as consultas de mídia, prefers-reduced-motion
pode ser verificado em um contexto CSS e em
JavaScript.
Para ilustrar ambos, digamos que eu tenha um botão importante de inscrição no qual quero que o usuário clique. Eu poderia definir uma animação "vibrar" que chame a atenção, mas, como um bom usuário da Web, vou reproduzi-la apenas para usuários que concordam explicitamente com as animações, mas não para os demais, que podem ser usuários que desativaram as 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, vamos imaginar que eu
defini 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 mudar, para animações JavaScript, preciso detectar as alterações e, em seguida, interromper manualmente minhas animações potencialmente 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 é tornar a reprodução de um AVIF, WebP ou GIF animado dependente do
atributo media
. Se (prefers-reduced-motion: no-preference)
for avaliado como true
, será seguro
exibir a versão animada. Caso contrário, a versão estática:
<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 abaixo. Tente alternar as preferências de movimento do dispositivo para conferir a diferença.
Descobrir as preferências do usuário no momento da solicitação
O cabeçalho de dica do cliente Sec-CH-Prefers-Reduced-Motion
permite que os sites acessem as preferências de movimento do usuário no momento da solicitação,
permitindo que os servidores in-line 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, tire um momento para apreciar a piada, é hilária e eu vou esperar. Agora que você voltou, vou apresentar a
demonstração. Quando você rola para baixo, cada status HTTP
aparece alternadamente no lado direito ou esquerdo. É uma animação de 60 QPS suave,
mas, conforme descrito acima, 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 até mesmo dinamicamente, para que os usuários possam
mudar a preferência deles imediatamente, sem precisar recarregar. Se um usuário preferir um movimento reduzido, as
animações de revelação desnecessárias vão desaparecer, e apenas o movimento de rolagem normal será deixado. O
screencast abaixo mostra a demonstração em ação:
prefers-reduced-motion
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. Você pode ler tudo sobre
prefers-color-scheme
no meu artigo Hello Darkness, My Old Friend 🌒.
No momento, 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 uma transparência reduzida),
prefers-contrast
(detecta se o usuário
pediu ao sistema para aumentar ou diminuir o contraste entre cores adjacentes)
e inverted-colors
(detecta se o usuário
prefere cores invertidas).
(Bônus) Forçando movimento reduzido em todos os sites
Nem todos os sites usam o prefers-reduced-motion
ou talvez não sejam suficientes para você.
Se você quiser, por qualquer motivo, interromper a movimentação em todos os sites, isso é possível. Uma maneira de fazer isso é injetar uma folha de estilo com o seguinte CSS em cada página da Web que você visitar. Existem várias extensões de navegador (use por sua conta e risco) que permitem isso.
@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 acima modifica a duração de todas as animações e transições
para um período 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 acionamento do
animationend
evento),
a abordagem mais radical animation: none !important;
não funcionaria. Nem mesmo a invasão acima
tem garantia de sucesso em todos os sites. Por exemplo, ela não pode interromper o movimento iniciado pela
API Web Animations (link em inglês). Portanto,
desative-a quando perceber uma interrupção.
Links relacionados
- Rascunho do editor mais recente da especificação de consultas de mídia de nível 5.
prefers-reduced-motion
em Status da plataforma do Chrome.prefers-reduced-motion
Bug do Chromium.- Blink Intenção de implementar a postagem (link em inglês).
Agradecimentos
Um agradecimento a Stephen McGruer, que implementou a
prefers-reduced-motion
no Chrome e, junto com
Rob Dodson, também analisou este artigo.
Imagem principal de Hannah Cauhepe no Unsplash.