Motion design: microinterações que fazem sentido
Objetivos deste capítulo
- Afinar duração, curva e propriedade de cada animação
- Coreografar as aparições e as transições no scroll
- Respeitar a performance e o prefers-reduced-motion
Uma página perfeita, mas imóvel
A landing Sereno está agora tipografada, com tema claro e escuro, acessível. O cliente percorre-a em silêncio, depois solta: «É muito bonita. Mas está… imóvel. Parece um cartaz.» O diretor do Studio Mango traduz: falta o motion — essa camada de movimento que faz com que uma interface pareça viva e responda sob os dedos. O capítulo 5 estabeleceu a regra (curtas, suaves, significantes); hoje, constróis o sistema de movimento completo, com o mesmo rigor que para as cores e a tipografia.
Porque é esse o ponto-chave: o motion concebe-se em tokens e regras, não em efeitos acrescentados caso a caso. Uma interface em que cada elemento se mexe à sua própria velocidade com a sua própria curva parece improvisada — exatamente como uma página com espaçamentos aleatórios. Um pequeno número de durações, uma ou duas curvas assinatura, regras de uso: eis o que vais entregar.
O movimento é uma linguagem funcional
Antes das afinações, o porquê. Uma animação bem concebida cumpre um de três papéis. O feedback: confirmar que uma ação foi percebida — o botão que se afunda ligeiramente ao clique diz «ouvi-te». A orientação: mostrar de onde vem e para onde vai um elemento — o painel que desliza da direita indica que se fechará para a direita. A continuidade: ligar dois estados de uma interface para que a mudança não seja um salto brutal — o cartão que se expande suavemente em vez de uma modal que surge do nada.
Toda a animação que não cumpre nenhum destes papéis é decorativa — ruído. Para uma app de meditação, o critério é ainda mais estrito: cada movimento deve apaziguar, nunca distrair. Pergunta-te para cada animação: «o que diz ela ao utilizador?». Se a resposta for «nada, mas é bonita», elimina-a. É a versão motion da caça ao genérico.
As três afinações: duração, curva, propriedade
Primeira decisão: a duração, proporcional à amplitude da mudança. Os micro-feedbacks (hover, focus, checkbox marcada) vivem entre 100 e 200 ms — mais curto parece instantâneo, mais longo parece mole. As transições médias (aparição de um cartão, abertura de um acordeão) entre 200 e 300 ms. Os grandes movimentos (painel lateral, mudança de página) entre 300 e 500 ms — para além disso, o utilizador espera pela interface, e a espera repetida torna-se irritação.
Segunda decisão: a curva de aceleração (easing). A regra física: o que entra no ecrã desacelera (ease-out — o elemento chega depressa e pousa suavemente), o que sai acelera (ease-in — escapa-se), o que se desloca no mesmo sítio faz os dois (ease-in-out). O linear fica reservado às rotações contínuas tipo spinner. E para dar uma assinatura à Sereno, define-se uma curva cubic-bezier própria, suave e ligeiramente amortecida, usada em todo o lado — é o equivalente motion da fonte de títulos.
:root {
/* Tokens de movimento — o sistema, não efeitos isolados */
--duration-fast: 150ms; /* micro-feedback: hover, focus */
--duration-base: 250ms; /* transições médias: cartões, acordeões */
--duration-slow: 400ms; /* grandes movimentos: painéis, páginas */
--ease-out-soft: cubic-bezier(0.25, 0.8, 0.35, 1); /* a assinatura Sereno */
--ease-in-soft: cubic-bezier(0.55, 0, 0.7, 0.4);
}
.btn {
transition:
background-color var(--duration-fast) var(--ease-out-soft),
transform var(--duration-fast) var(--ease-out-soft),
box-shadow var(--duration-fast) var(--ease-out-soft);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(0.98); }--ease-out-soft) e proíbe os easings improvisados nos prompts, exatamente como proíbes as cores fixas.Performance: anima apenas transform e opacity
Terceira decisão, a mais técnica: a propriedade animada. Nem todas as propriedades CSS se equivalem. Animar width, height, top ou margin obriga o navegador a recalcular o layout de toda a zona a cada frame — num telemóvel médio, a animação fica aos solavancos. Animar transform (translação, escala, rotação) e opacity é tratado diretamente pelo processador gráfico: fluido a 60 imagens por segundo, mesmo em hardware modesto.
A tradução prática: um elemento que «sobe» no hover usa transform: translateY(-2px), nunca top: -2px. Um painel que se abre desliza com translateX, não muda a sua width. Uma aparição combina opacity e uma pequena translação. Acrescenta esta restrição a todos os teus prompts de motion — é uma daquelas exigências que a IA respeita perfeitamente quando é formulada, e esquece uma vez em cada duas caso contrário.
will-change: útil pontualmente para preparar uma animação pesada, consome memória se for posto em todo o lado «por precaução». A regra: acrescentá-lo apenas se uma animação ficar realmente aos solavancos, e retirá-lo depois da animação.Coreografia: ordenar as aparições
Uma página não aparece de um bloco: ela conta-se. A coreografia consiste em ordenar as aparições segundo a hierarquia de leitura: o título primeiro, o subtítulo depois, o CTA por fim — cada um desfasado de 50 a 80 ms em relação ao anterior. Este desfasamento (o «stagger») é suficientemente curto para que o conjunto pareça fluido, suficientemente longo para que o olho siga o fio. Os três cartões de benefícios aparecem em cascata da esquerda para a direita, não todos ao mesmo tempo.
flowchart LR L["Carregamento da secção"] --> T["Título: aparição imediata"] T --> ST["Subtítulo: desfasamento de 60 ms"] ST --> CTA["CTA: desfasamento de 120 ms"] CTA --> C1["Cartão 1"] C1 --> C2["Cartão 2: mais 70 ms"] C2 --> C3["Cartão 3: mais 140 ms"]
Aparições no scroll, com sobriedade
O grande clássico das landing pages: as secções que se revelam suavemente à medida que se faz scroll. Bem doseado, o efeito dá ritmo à leitura; em excesso, transforma a página num parque de diversões. As regras de sobriedade: uma distância de deslocamento curta (12 a 16 px, não 100), uma aparição única (o elemento fica visível depois de revelado, não repete a animação a cada passagem), e um único tipo de efeito para toda a página — fade + ligeira subida, ponto final. Nada de zoom aqui, rotação ali, ressalto acolá.
/* CSS: o estado inicial e o estado revelado */
.reveal {
opacity: 0;
transform: translateY(14px);
transition: opacity var(--duration-slow) var(--ease-out-soft),
transform var(--duration-slow) var(--ease-out-soft);
}
.reveal.is-visible { opacity: 1; transform: none; }// JS: IntersectionObserver — revela uma única vez
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
observer.unobserve(entry.target); // uma única vez
}
}
}, { threshold: 0.15 });
document.querySelectorAll('.reveal').forEach((el) => observer.observe(el));Acrescenta um sistema de motion completo à landing Sereno (código em anexo): - tokens: --duration-fast 150ms, --duration-base 250ms, --duration-slow 400ms, curva assinatura cubic-bezier(0.25, 0.8, 0.35, 1) - micro-feedbacks: hover e active em botões, cartões e links (transform + sombra, nunca top/width) - coreografia da hero: título, depois subtítulo (+60ms), depois CTA (+120ms), em fade + translateY(14px) - aparições no scroll: secções em fade + subida de 14px, uma única vez, via IntersectionObserver - RESTRIÇÕES: anima apenas transform e opacity; nenhuma animação com mais de 500ms; nenhum ressalto nem efeito elástico - acrescenta o bloco @media (prefers-reduced-motion: reduce) que desativa translações e stagger mantendo simples fades rápidos Entrega o CSS e o JS separados, comentados.
prefers-reduced-motion: não negociável
Uma parte dos utilizadores sofre de perturbações vestibulares: os movimentos de interface — parallax, deslizamentos amplos, zooms — causam-lhes vertigens e náuseas reais. Outros preferem simplesmente uma interface calma. Todos podem ativar «reduzir as animações» no seu sistema, e o teu CSS deve escutá-lo através da media query prefers-reduced-motion: reduce. Reduzir não quer dizer partir tudo: substituem-se as translações por simples fades curtos, e eliminam-se as animações puramente decorativas. A interface continua viva, deixa de se mover no espaço.
@media (prefers-reduced-motion: reduce) {
.reveal {
transform: none; /* fim do deslocamento espacial */
transition: opacity 120ms ease; /* um simples fade curto */
}
.btn:hover, .btn:active { transform: none; }
}Para uma app de meditação, a ironia seria cruel: provocar náuseas ao utilizador que veio procurar a calma. Integra a media query desde o primeiro prompt de motion (como acima), não como corretivo de última hora — e acrescenta este ponto à tua lista de verificação de entrega, ao mesmo nível dos contrastes.
Quando não animar
Auditoria de motion da landing Sereno (código em anexo). Elabora uma tabela exaustiva de cada animação: - elemento em causa, gatilho, duração, curva, propriedades animadas - o seu papel: feedback, orientação ou continuidade — escreve «NENHUM» se for puramente decorativa - conformidade: propriedades limitadas a transform/opacity? duração abaixo de 500 ms? comportamento definido sob prefers-reduced-motion? Depois: 1. lista as animações a ELIMINAR (papel NENHUM) com uma frase de justificação 2. lista as não-conformidades técnicas e a sua correção 3. verifica que todas as durações e curvas provêm dos tokens --duration-* e --ease-*, e assinala todo o valor fixo
Termina com o inventário crítico: pede à IA a lista de todas as animações da página com a sua duração, a sua propriedade e o seu papel (feedback, orientação, continuidade). Toda a linha cujo papel fique vazio é candidata à eliminação. Verás quase sempre o mesmo resultado: a página final tem menos animações do que a versão intermédia, mas cada uma é certeira. O motion premium parece-se com a montagem de um bom filme — não se notam os cortes, sente-se apenas que tudo flui. O cliente não dirá «belas animações»; dirá «é apaziguante», e é exatamente essa a missão.
Contexto
«Está imóvel», disse o cliente. Tens uma tarde para acrescentar a camada de movimento à landing Sereno: micro-feedbacks, coreografia da hero, revelações no scroll — tudo fluido num telemóvel de entrada de gama e respeitador do prefers-reduced-motion. O diretor será intransigente num ponto: nem um único movimento gratuito.
Instruções
- Define os teus tokens de motion: três durações (150/250/400 ms) e uma curva assinatura cubic-bezier, acrescentadas ao design system.
- Acrescenta os micro-feedbacks aos botões, cartões e links — unicamente transform e opacity, transições de 150 ms.
- Coreografa a hero: título, subtítulo, CTA em cascata com um stagger de 60 ms, em fade + subida de 14 px.
- Implementa as revelações no scroll com IntersectionObserver: um único tipo de efeito, uma única vez por elemento.
- Acrescenta o bloco prefers-reduced-motion que substitui todo o deslocamento por um fade curto, e testa-o ativando a opção no teu sistema.
- Pede o inventário crítico: lista de cada animação com o seu papel (feedback, orientação, continuidade) — elimina toda a linha sem papel.
Em resumo
- O motion concebe-se em sistema: tokens de durações, curva assinatura, regras de uso — não em efeitos isolados.
- Cada animação cumpre um papel: feedback, orientação ou continuidade — senão é ruído a eliminar.
- Durações: 100-200 ms para os micro-feedbacks, 200-300 ms para as transições, 300-500 ms para os grandes movimentos.
- Ease-out para o que entra, ease-in para o que sai, ease-in-out para o que se desloca; linear reservado às rotações contínuas.
- Animam-se apenas transform e opacity: as outras propriedades fazem os telemóveis modestos ficar aos solavancos.
- A coreografia segue a hierarquia de leitura com um stagger de 50-80 ms; no scroll: um único efeito, uma única vez, 12-16 px.
- O prefers-reduced-motion não é negociável: substituir os deslocamentos por fades curtos, desde o primeiro prompt.
Quiz — verifica a tua compreensão
1. Quais são os três papéis legítimos de uma animação de interface?
2. Que duração convém a um micro-feedback de hover?
3. Porquê animar apenas transform e opacity?
4. Que curva de aceleração para um elemento que entra no ecrã?
5. O que deve fazer o bloco prefers-reduced-motion: reduce?
6. O que é um «stagger» numa coreografia de aparição?