Apostila completa de Motion de Interface
Motion de interface é o design do movimento numa UI: como as coisas entram, saem, mudam e respondem ao toque. Esta apostila cobre as funções do movimento e seu custo, os princípios da animação aplicados a produto, timing e easing, os tipos de transição, coreografia, micro-interações, a técnica e a performance na web, as ferramentas e o handoff, e como tudo isso vira motion tokens num design system — com acessibilidade no centro.
Por que movimento em UI
Objetivo: entender as funções que o movimento cumpre numa interface, o custo que ele impõe, e o critério de "motion com propósito".
1.1 O que o movimento faz por uma interface
| Função | Exemplo |
|---|---|
| Orientar a atenção | um item novo desliza para a lista; um erro treme sutilmente |
| Mostrar causa e efeito | o menu sai do botão que você tocou; o card expande para a tela de detalhe |
| Manter continuidade espacial | a tela nova entra pela direita → "avancei"; volta pela esquerda → "voltei" |
| Dar feedback | o botão afunda ao ser pressionado; o toggle desliza; o pull-to-refresh estica |
| Mascarar espera | skeleton pulsando, transição que cobre os 200ms de carregamento |
| Expressar a marca | a "personalidade" do easing e do timing — brincalhão, preciso, sóbrio |
1.2 O custo do movimento
- Tempo: toda animação adiciona latência percebida. Uma transição de 500ms repetida 40 vezes ao dia é 20 segundos de espera imposta.
- Distração: movimento na periferia rouba atenção involuntariamente — bom para alertar, péssimo para deixar ligado.
- Enjoo: parallax, zoom e movimento grande podem causar desconforto vestibular em parte real da população (Módulo 9).
- Custo técnico: animação mal feita causa jank (queda de frames) e gasta bateria.
Toda animação precisa de um trabalho. Se você não consegue dizer em uma frase o que aquele movimento informa — de onde algo veio, o que mudou, que a ação foi registrada — ele é decoração, e decoração em UI envelhece rápido, atrasa e distrai. Na dúvida, mais curto; na dúvida de novo, sem animação.
1.3 Os quatro tempos do motion em produto
- Micro-interações (Módulo 6): resposta imediata a um toque — 100–200ms.
- Transições de estado: um elemento muda (abre, expande, some) — 200–300ms.
- Transições de tela/rota (Módulo 4): navegação — 250–400ms.
- Momentos expressivos: onboarding, sucesso, estado vazio — podem durar mais, porque a espera é a experiência.
Perguntas de abertura: "Para que serve animação numa interface?" (orientar atenção, mostrar causa-efeito, continuidade espacial, feedback, mascarar espera, marca), "Qual o custo de animar?" (latência percebida, distração, enjoo, jank/bateria), "Como você decide se um movimento deve existir?" (ele precisa informar algo em uma frase; senão, corta).
✏️ Exercício 1 — Propósito ou decoração
Para cada animação, diga a função (em uma frase) ou marque como decoração a cortar: (a) o menu lateral desliza da borda esquerda ao abrir; (b) todos os cards da home fazem um "bounce" ao carregar; (c) o número de notificações incrementa com um flip; (d) o fundo da página tem um gradiente que gira lentamente sem parar; (e) o botão de enviar vira um spinner e depois um check.
Gabarito: (a) função: continuidade espacial — o menu vem "de fora da tela", reforçando que é uma camada lateral. (b) decoração — o bounce não informa nada, atrasa a leitura e vai cansar; cortar (ou um fade/stagger sutil no máximo). (c) função: orientar atenção para a mudança de valor. (d) decoração + risco — movimento perpétuo na periferia distrai e pode causar desconforto; cortar ou tornar estático. (e) função: feedback de estado (registrado → processando → concluído) — mantém, curto.
Os princípios da animação aplicados a UI
Objetivo: adaptar os princípios clássicos da animação (Disney) para interface — quais transferem, quais não, e como.
2.1 De Disney para o produto
Os "12 princípios" (Johnston & Thomas, The Illusion of Life) foram escritos para personagens desenhados. Alguns são a base do motion de UI; outros quase não se aplicam.
| Princípio | Em UI |
|---|---|
| Timing | essencial — a duração comunica peso e distância (Módulo 3) |
| Slow in / slow out (easing) | essencial — nada se move em velocidade constante no mundo real nem numa boa UI |
| Staging | essencial — dirigir o olhar para uma coisa por vez (coreografia, Módulo 5) |
| Follow-through / overlap | útil, com moderação — um leve atraso entre elementos que se movem juntos dá naturalidade |
| Anticipation | às vezes — um micro-recuo antes de um elemento sair; fácil exagerar |
| Secondary action | útil — o ícone que gira enquanto o painel abre |
| Squash & stretch | pouco e sutil — um botão que "amassa" 2–3% ao ser pressionado; muito = brinquedo |
| Arcs | às vezes — elementos que percorrem um leve arco em vez de linha reta parecem mais orgânicos |
| Exaggeration, Appeal, Solid drawing, Straight-ahead vs pose-to-pose | quase não se aplicam a UI funcional |
2.2 Os princípios de UI (Material Motion e afins)
- Informativo: o movimento diz de onde algo vem, para onde vai, e o que se relaciona com o quê.
- Focado: dirige a atenção sem distrair; um elemento em movimento por vez.
- Expressivo: reforça a marca e o "toque" do produto — mas por último, depois de informativo e focado.
- Consistente: a mesma classe de mudança usa a mesma duração e easing em todo o produto (motion tokens, Módulo 9).
- Rápido: a animação nunca deve fazer o usuário esperar por algo que já poderia estar pronto.
Perguntas: "Quais princípios da animação clássica se aplicam a UI?" (timing, easing, staging, follow-through/overlap — com moderação), "E quais não?" (exaggeration, appeal, solid drawing), "O que é squash & stretch em UI?" (um leve "amassar" no toque; muito vira brinquedo), "Qual a ordem de prioridade das qualidades do motion?" (informativo → focado → expressivo).
✏️ Exercício 2 — Aplique (com moderação)
Um FAB (botão flutuante) abre um menu de 3 ações. Descreva como você aplicaria: staging, easing, follow-through/overlap e secondary action — e onde você não usaria exaggeration.
Gabarito (uma boa resposta): Staging: o menu emerge do próprio FAB (causa-efeito) e as outras 3 ações aparecem em sequência, não todas de uma vez, dirigindo o olhar. Easing: ease-out na abertura (rápido a sair, desacelera ao pousar), ease-in no fechamento. Follow-through/overlap: as 3 ações têm um stagger de ~30–40ms entre si e "assentam" com um leve settle, não param secamente. Secondary action: o ícone do FAB rotaciona (ex.: + vira ×) durante a abertura. Sem exaggeration: nada de os itens "estourarem" em escala 1.4 e voltarem, nem de bounce grande — isso chama atenção para a animação, não para as ações, e cansa no uso repetido.
Timing e easing
Objetivo: escolher durações e curvas de aceleração certas — o que muda tudo numa animação — e entender springs.
3.1 Duração
| Tipo de mudança | Duração típica |
|---|---|
| Micro-interação (hover, toggle, ripple, ícone) | 100–200ms |
| Elemento pequeno entrando/saindo (tooltip, menu, chip) | 150–250ms |
| Elemento grande / painel / bottom sheet | 250–400ms |
| Transição de tela / rota | 250–400ms (mobile costuma ser mais lento que web) |
| Momento expressivo (sucesso, onboarding) | 400–800ms+ |
- Maior/mais distante = mais tempo. Um elemento que atravessa a tela leva mais que um que se move 8px.
- Saídas mais rápidas que entradas — o usuário já decidiu; não o faça esperar para "ir embora".
- Acima de ~400ms para interação comum, a UI começa a parecer lenta.
3.2 Easing (curvas de aceleração)
/* os quatro casos que resolvem quase tudo */ --ease-out: cubic-bezier(0.0, 0.0, 0.2, 1); /* entra: rápido → desacelera. O default. */ --ease-in: cubic-bezier(0.4, 0.0, 1, 1); /* sai: acelera → some */ --ease-in-out: cubic-bezier(0.4, 0.0, 0.2, 1); /* move de A para B, na tela o tempo todo */ --ease-standard: cubic-bezier(0.2, 0.0, 0, 1); /* "emphasized" — mais caráter */
linearé quase sempre errado para movimento (ok para opacidade pura e para progресso contínuo/spinner).- Entrada →
ease-out("fast out, slow in"): o elemento chega com energia e assenta suave. É o mais natural e o mais usado. - Saída →
ease-in: acelera para fora. - Mover algo que permanece visível →
ease-in-out. - Overshoot / "back" (passar do ponto e voltar): use com muita parcimônia, só em momentos lúdicos.
3.3 Springs (molas)
- Em vez de duração + curva, uma spring é definida por stiffness (rigidez), damping (amortecimento) e mass — e a duração emerge da física.
- Vantagens: naturalidade, interrompibilidade (o usuário arrasta de novo no meio e a mola responde sem "pular"), continuidade de velocidade em gestos.
- Padrão em iOS, no Framer Motion, no React Spring. Para a maioria dos casos de UI, uma spring "sem bounce" (damping alto) parece um bom ease-out — a diferença aparece em gestos e interrupções.
3.4 A relação duração × distância × easing
Não existe "300ms é o certo". Um menu que desce 200px com ease-out em 250ms parece ágil; o mesmo menu em linear parece mecânico; em 500ms parece preguiçoso; movendo 600px em 250ms parece um borrão. Ajuste os três juntos, testando no device.
Perguntas: "Que duração para uma transição de UI?" (100–200ms micro, 200–400ms transições; maior/mais longe = mais tempo; saídas mais rápidas), "Por que ease-out para entradas?" ("fast out, slow in" — chega com energia e assenta), "Quando linear?" (quase nunca; ok para opacidade e spinner), "O que é uma spring e qual a vantagem?" (física em vez de duração; interrompível, natural em gestos).
✏️ Exercício 3 — Especifique timing e easing
Para (a) um tooltip que aparece no hover, (b) um bottom sheet que o usuário arrasta para cima, (c) uma tela de detalhe que entra ao tocar num item, (d) um toast de erro que aparece e some sozinho — dê duração, easing (ou spring) de entrada e de saída, e justifique.
Gabarito (uma boa resposta): (a) tooltip: entrada ~120ms ease-out (fade + 4px de subida); saída ~80ms ease-in (só fade). Pequeno e frequente → curtíssimo. (b) bottom sheet: spring (damping médio, sem bounce) — porque é dirigido por gesto e precisa ser interrompível e continuar a velocidade do dedo; ao soltar, a mola leva ao snap. (c) tela de detalhe: ~300ms; entrada ease-out com shared element (o card cresce para virar o header) ou slide da direita; saída ~250ms ease-in voltando pela direita. (d) toast: entrada ~200ms ease-out (slide de baixo + fade); permanência 4–6s; saída ~150ms ease-in (fade + leve descida). O erro pode ter um micro-shake de 1 ciclo na entrada para chamar atenção, respeitando reduced-motion.
Tipos de transição
Objetivo: conhecer o repertório de transições — enter/exit, shared element, container transform, stagger, reveal, parallax — e escolher pela mensagem, não pela aparência.
4.1 Enter / exit
- Fade: a mais neutra — "isto apareceu/sumiu". Boa para elementos sem posição forte (overlays, mensagens).
- Slide: carrega direção e origem — o menu vem da borda, a tela vem da direita. Diz "de onde".
- Scale: "isto cresceu a partir daqui" — bom para popovers e menus que emanam de um gatilho (ancorar a origem da escala no gatilho).
- Fade + move curto (8–16px): o combo mais usado para listas e cards — presença sem drama.
4.2 Shared element / hero transition
Um elemento que existe nas duas telas (a miniatura na lista → a imagem grande no detalhe) persiste e se transforma em vez de sumir e reaparecer. É a transição mais poderosa para continuidade: o usuário nunca "perde" o objeto de vista. Na web, a View Transitions API faz isso nativamente (Módulo 7).
4.3 Container transform
Um contêiner (um card, um FAB, uma barra de busca) cresce e vira a próxima superfície (a tela de detalhe, o formulário, a lista de resultados). O conteúdo antigo dá fade-out e o novo fade-in dentro do contêiner que se expande. Comunica "isto abriu daqui".
4.4 Stagger (cascata)
- Itens de uma lista/grade entram com um atraso incremental pequeno (20–50ms entre itens), não todos juntos.
- Dá ritmo e ajuda o olho a perceber que são itens separados.
- Limite o total: acima de ~8–10 itens, o stagger acumula e a última linha demora demais — corte o delay a partir de um ponto, ou anime só o que está na viewport.
4.5 Reveal, morph e parallax
- Reveal: um clip/máscara que "abre" o conteúdo (accordion, "ler mais") — anime a altura/clip, com o conteúdo em fade.
- Morph: uma forma vira outra (ícone hambúrguer → X; play → pause) — Módulo 6 da apostila Iconografia.
- Parallax: camadas em velocidades diferentes no scroll → profundidade. Efeito caro em atenção e em conforto — sutil, e desligado em
prefers-reduced-motion.
4.6 Escolher pela mensagem
| O que você quer comunicar | Transição |
|---|---|
| "isto apareceu, sem origem específica" | fade (+ move curto) |
| "isto veio de fora / desta direção" | slide |
| "isto emana deste gatilho" | scale a partir da origem, ou container transform |
| "este objeto continua sendo o mesmo" | shared element |
| "estes são vários itens distintos" | stagger |
| "avancei / voltei na navegação" | slide horizontal consistente com a direção |
Perguntas: "Qual transição para abrir uma tela de detalhe a partir de um card?" (shared element ou container transform — continuidade do objeto), "Quando fade vs slide?" (fade = sem origem; slide = direção/origem), "O que é stagger e qual o cuidado?" (atraso incremental; não deixar a última linha demorar — limitar ou animar só o visível), "Por que cuidado com parallax?" (atenção e conforto vestibular).
✏️ Exercício 4 — Escolha as transições
Um app de e-commerce: (a) abrir o carrinho (painel lateral); (b) da grade de produtos para a página do produto; (c) adicionar item ao carrinho (o item "voa" para o ícone?); (d) a lista de resultados após aplicar um filtro. Para cada, escolha a transição e diga o que ela comunica.
Gabarito (uma boa resposta): (a) slide da borda direita + overlay em fade — "é uma camada lateral que veio de fora"; saída mais rápida. (b) shared element (a imagem do produto persiste e cresce) ou container transform do card — "é o mesmo produto, você não o perdeu". (c) um fly-to-cart curto (a miniatura percorre um arco até o ícone do carrinho, que dá um pulso) — feedback claro de "foi adicionado"; manter < 400ms e com fallback estático em reduced-motion. (d) stagger sutil (fade + move curto, 20–30ms entre itens, só os visíveis) + talvez um crossfade da lista antiga para a nova — "a lista mudou, estes são novos itens".
Coreografia e orquestração
Objetivo: reger múltiplos elementos que se movem — ordem, atraso, hierarquia, continuidade — para que a cena conte uma história clara.
5.1 Um assunto por vez
Quando muitas coisas mudam ao mesmo tempo, o olho não sabe onde pousar. Coreografia é sequenciar: o que se move primeiro, o que espera, o que se move junto. A regra: em cada instante, deve haver um foco de movimento — o resto ou está parado, ou se move de forma discreta e subordinada.
5.2 Hierarquia de movimento
- Primário: o elemento sobre o qual a ação é (o card que você tocou, o painel que abre).
- Secundário: o que reage ao primário (o conteúdo ao redor que dá espaço, o backdrop que escurece).
- Terciário / ambiente: detalhes (um ícone que gira, uma sombra que cresce) — quase imperceptíveis.
- Dê ao primário mais deslocamento e mais "presença"; ao resto, menos.
5.3 Continuidade: o que persiste vs o que troca
- Identifique os elementos que existem antes e depois da transição (o header, a foto, o título) e faça-os persistir e se mover, nunca sumir e reaparecer.
- O que é novo entra; o que sai de cena sai — e idealmente na direção que faz sentido espacial.
- Isso é o "shared element" pensado no nível da tela inteira: um modelo espacial consistente (o app como um lugar por onde você se move).
5.4 Stagger e delays com intenção
- Stagger na ordem de leitura (de cima para baixo, do gatilho para fora), não aleatório.
- Delays para encadear: o painel abre (0ms) → o conteúdo dele entra (120ms depois, quando já há espaço) → o CTA pulsa (no fim).
- Cuidado com o tempo total: a soma de todos os delays não pode fazer a cena demorar > ~500–600ms para o essencial estar utilizável.
5.5 Interrupção e reversibilidade
- O usuário pode tocar de novo no meio da animação. A transição precisa ser interrompível e reversível — voltar do ponto atual, não "terminar e então reverter" (springs ajudam; Módulo 3).
- Nunca bloqueie a interface durante uma transição não essencial.
Antes de mexer na ferramenta, desenhe a cena em 3–5 quadros: estado inicial → o que se move primeiro → depois → estado final. Anote para cada elemento: persiste ou troca? primário, secundário ou ambiente? A maioria dos "motion bagunçado" é falta desse storyboard — não de habilidade com curvas.
Perguntas: "O que é coreografia em motion de UI?" (sequenciar múltiplos elementos; um foco de movimento por vez; hierarquia primário/secundário/ambiente), "Como você mantém continuidade numa transição de tela?" (identificar o que persiste e movê-lo, não sumir/reaparecer; modelo espacial consistente), "Como o stagger deve ser ordenado?" (ordem de leitura / a partir do gatilho), "Por que a transição precisa ser interrompível?".
✏️ Exercício 5 — Coreografe a cena
Ao tocar num e-mail na lista, abre a tela de leitura. Elementos: remetente + assunto (existem nas duas telas), corpo do e-mail (novo), barra de ações (nova), a lista (sai). Faça o storyboard em 4 quadros e atribua ordem, papel (primário/secundário/ambiente) e persistência a cada elemento.
Gabarito (uma boa resposta): Q1 (0ms): lista visível, item tocado destacado. Q2 (~50ms): o item toca começa a expandir (primário); remetente + assunto persistem e deslizam/crescem para a posição de header; a lista atrás começa a dar fade/deslocar (ambiente). Q3 (~200ms): o contêiner do item agora ocupa a tela; o corpo do e-mail entra em fade + move curto (secundário, ordem de leitura de cima para baixo); a lista já saiu. Q4 (~320ms): a barra de ações entra por último (de baixo, ou fade) — terciária, quando o resto já assentou. Reverso: tocar em "voltar" reverte com a lista voltando e o header encolhendo de volta ao item. Tempo total até "legível": ~250ms; total até assentar: ~350ms. Interrompível a qualquer momento.
Micro-interações
Objetivo: projetar as pequenas respostas ao toque — a anatomia (trigger, rules, feedback, loops/modes) e os padrões (botão, toggle, input, pull-to-refresh, like, swipe).
6.1 A anatomia (Dan Saffer)
- Trigger (gatilho): o que inicia — um toque, um hover, um evento do sistema (chegou mensagem), um limite atingido.
- Rules (regras): o que acontece e sob que condições.
- Feedback: o que o usuário vê/sente/ouve — a parte visível, e onde o motion entra.
- Loops & modes: a duração e o que muda ao longo do tempo (o botão "curtido" fica curtido; o "não perturbe" persiste).
6.2 Feedback imediato
- A resposta ao toque deve começar em < 100ms — abaixo disso é "instantâneo"; acima, parece travado.
- Estados de um controle: repouso → hover (ponteiro) → pressed (afunda, escurece, ripple) → foco (
:focus-visible) → disabled → loading. Cada um com sua micro-transição (100–150ms). - O pressed deve responder ao pointerdown, não ao click — feedback antes da confirmação.
6.3 Padrões comuns
| Micro-interação | Motion |
|---|---|
| Toggle / switch | o "polegar" desliza (ease-out ~150ms); a trilha muda de cor no mesmo tempo; opcional: leve overshoot |
| Checkbox | o check se "desenha" (stroke-dashoffset, ~150ms) + o box preenche |
| Input focus | a borda/label anima para o estado ativo (label sobe — "floating label"); ~120ms |
| Like / favorito | escala rápida 1→1.15→1 + preenchimento + burst opcional de partículas |
| Pull-to-refresh | o indicador segue o dedo (1:1), resiste no fim (rubber band), solta → spinner |
| Swipe para ação | o item segue o dedo, revela a ação por baixo, snap ao soltar; cor/ícone confirmam |
| Botão de envio | repouso → spinner (largura colapsa para círculo) → check → sucesso |
6.4 O que uma boa micro-interação faz
- Confirma que a ação foi registrada (sobretudo antes de o resultado chegar).
- Comunica o estado resultante (ligado/desligado, curtido, enviado).
- Previne erro (o rubber band diz "chegou no limite"; o swipe pela metade volta).
- Dá um pequeno prazer — mas esse é o quarto objetivo, nunca o primeiro.
Perguntas: "Qual a anatomia de uma micro-interação?" (trigger, rules, feedback, loops/modes), "Em quanto tempo o feedback ao toque deve começar?" (< 100ms; pressed no pointerdown), "Descreva a micro-interação de um toggle" (polegar desliza + trilha muda de cor, ~150ms ease-out), "O que uma boa micro-interação faz?" (confirma, comunica estado, previne erro; prazer por último).
✏️ Exercício 6 — Projete a micro-interação
Projete a micro-interação completa de um botão "Salvar" que faz uma chamada de rede: liste trigger, rules, feedback (com timing e motion de cada estado) e loops/modes. Inclua o caminho de erro.
Gabarito (uma boa resposta): Trigger: pointerdown/click no botão. Rules: se o formulário é válido, dispara o request; se inválido, não envia e sinaliza os campos. Feedback: pointerdown → estado pressed (escurece + amassa 2%, ~80ms); ao soltar → o rótulo "Salvar" some e a largura do botão colapsa para um círculo com spinner (~200ms ease-in-out); o botão fica desabilitado para novo clique. Sucesso → o spinner vira um check que se desenha (~200ms), cor muda para sucesso, e após ~800ms volta ao repouso (ou o formulário fecha). Erro → o círculo volta a expandir para o botão, um shake horizontal de 1 ciclo (~200ms, respeitando reduced-motion → sem shake, só cor), rótulo vira "Tentar de novo", e uma mensagem inline aparece. Loops & modes: enquanto salva, o botão está em modo "ocupado" (sem repetir o request); após sucesso, modo "salvo" por alguns segundos.
Motion na web: técnica e performance
Objetivo: animar na web a 60fps — o que é barato animar, FLIP, Web Animations API, View Transitions, scroll-driven animations e as bibliotecas.
7.1 O que é barato animar
- Barato (compositor, sem recalcular layout):
transform(translate, scale, rotate) eopacity. Anime só isso sempre que possível. - Caro (dispara layout e/ou paint a cada frame):
width,height,top/left,margin,box-shadow,filterpesado,background-position. - Truques: para "animar largura", anime
transform: scaleX()e contra-escale o conteúdo; para sombra, faça cross-fade entre duas camadas de sombra; para posição,translate, nãotop/left. will-change: transformavisa o navegador — use com moderação (cada camada custa memória) e remova depois.
7.2 CSS: transition, animation, @keyframes
.card{
transition: transform 200ms var(--ease-out), opacity 200ms linear;
}
.card:hover{ transform: translateY(-4px); }
@keyframes slide-up{
from{ opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: none; }
}
.enter{ animation: slide-up 240ms var(--ease-out) both; }
- CSS resolve a maioria das entradas/saídas, hovers e loops simples — sem JS.
@starting-styleetransition-behavior: allow-discretepermitem animar a entrada de elementos que aparecem (dedisplay:none) e opopover/<dialog>.
7.3 FLIP
FLIP (First, Last, Invert, Play): para animar uma mudança de layout de forma barata — meça a posição First, aplique o estado Last, calcule a diferença e aplique um transform que Inverte (parece que nada mudou), depois Play removendo o transform com transição. Anima reordenações, "expandir para tela cheia", trocas de grid — usando só transform.
7.4 Web Animations API e bibliotecas
- WAAPI (
element.animate(keyframes, options)): controle no JS (play/pause/reverse/seek,onfinish), performático, sem dependência. Bom para coreografia dinâmica. - Motion One / GSAP: timelines, sequenciamento, easing avançado, plugins (morph, scroll). GSAP é o padrão para motion complexo.
- Framer Motion (Motion for React) / React Spring: springs, gestos, layout animations (FLIP embutido em
layout),AnimatePresencepara exit. Ótima DX em React.
7.5 APIs modernas do navegador
- View Transitions API:
document.startViewTransition(() => updateDOM())— o navegador tira um "antes" e "depois" e faz o crossfade/morph, inclusive shared elements viaview-transition-name. Funciona para SPA e, cada vez mais, para navegação entre páginas (MPA). - Scroll-driven animations:
animation-timeline: scroll()/view()— animações ligadas ao scroll sem JS e sem jank (reveal ao entrar na viewport, barra de progresso, parallax). Ver CSS Avançado: Animações & SVG. - Sempre com fallback: navegadores sem suporte simplesmente pulam para o estado final.
7.6 Medir
- 60fps = ~16.7ms por frame. Use o painel Performance/Rendering do DevTools: procure long tasks, layout thrashing e frames vermelhos.
- Teste em device intermediário real e com CPU throttling — não no seu desktop.
- Ative "Paint flashing" e "Layer borders" para ver o que está sendo repintado.
Animar width/height/top/left/margin (jank). box-shadow animado num loop. will-change em tudo, para sempre. Animar dentro de um requestAnimationFrame feito à mão quando CSS/WAAPI bastaria. Esquecer o exit (elementos somem sem transição porque saem do DOM). Nenhum fallback para APIs novas. Não testar em device fraco. Ignorar prefers-reduced-motion (Módulo 9).
Perguntas de front-end: "O que é barato animar e por quê?" (transform e opacity — só compositor; width/top disparam layout), "Explique FLIP", "O que a View Transitions API faz?" (crossfade/morph automático entre estados do DOM, com shared elements), "CSS, WAAPI ou uma lib?" (CSS para o simples; WAAPI para controle; GSAP/Framer Motion para complexo/gestos), "Como você garante 60fps?".
✏️ Exercício 7 — Torne performático
Um accordion anima height de 0 a auto; uma lista reordenável anima top dos itens; um card no hover anima box-shadow e margin-top. Reescreva cada um para rodar no compositor, dizendo a técnica.
Gabarito (uma boa resposta): Accordion: não animar height:auto. Opções: (a) medir a altura e animar height de 0 até esse valor em px via WAAPI (dispara layout mas uma vez por frame só nesse elemento — aceitável para um accordion), ou (b) melhor: grid-template-rows: 0fr → 1fr com overflow:hidden (anima sem medir), ou (c) FLIP no contêiner. O conteúdo em fade com opacity. Lista reordenável: FLIP — medir posições (First), aplicar a nova ordem (Last), aplicar transform: translateY() invertendo, e transicionar o transform para 0. Ou layout do Framer Motion (que faz FLIP). Card hover: pré-renderizar a sombra "elevada" como um pseudo-elemento com opacity:0 e animar a opacity dele; a "subida" com transform: translateY(-4px) em vez de margin-top.
Ferramentas, spec e handoff
Objetivo: prototipar motion, especificá-lo sem ambiguidade e entregá-lo para o desenvolvimento de forma que chegue igual à intenção.
8.1 Ferramentas de prototipagem
| Ferramenta | Forte em |
|---|---|
| Figma — Smart Animate | transições entre frames por elementos de mesmo nome; rápido para explorar enter/exit, shared element; limitado em lógica |
| After Effects + Lottie (Bodymovin) | animações complexas, ilustrativas, de estado vazio/onboarding; exporta JSON leve para web/mobile |
| Rive | state machines interativas, personagens, ícones e ilustrações que respondem a input/estado; runtime próprio |
| ProtoPie / Principle / Origami | protótipos de alta fidelidade com sensores, variáveis e lógica — para validar antes de codar |
| Código (CodePen, um branch) | a "verdade" — quando a fidelidade precisa ser exata, prototipe no meio final |
8.2 A spec de motion
Um protótipo bonito não é uma especificação. Para cada animação, documente:
- Gatilho: o evento (tap, hover, aparição, sucesso do request…).
- Propriedades: o que muda (
transform: translateY,opacity,scale…), com valores de/para. - Duração e easing (a curva exata:
cubic-bezier(...)ou os parâmetros da spring). - Delay e, em coreografias, o stagger e a ordem.
- Estado inicial e final (e o que acontece se interrompido).
- Comportamento com
prefers-reduced-motion(Módulo 9). - Referência aos motion tokens quando existirem ("usa
--duration-md+--ease-emphasized").
8.3 Handoff
- Entregue a spec + um vídeo em câmera lenta (ou o protótipo) + os tokens. Palavras como "suave" e "rápido" não são spec.
- Alinhe cedo com engenharia o que é viável na plataforma (o que a web/o iOS/o Android fazem bem e mal) — evita projetar o impossível.
- Revise no build real, no device real: o que parece ótimo no Figma frequentemente precisa de ajuste de 50ms no código.
- Para Lottie/Rive: entregue o arquivo + os nomes das state machines/markers + em que evento cada um dispara.
8.4 Performance budget
- Alvo: 60fps (ou 120 onde houver), sem frames perdidos durante a animação.
- Orçamento de peso para Lottie/vídeo (ex.: < 50KB para um ícone animado; um Lottie de onboarding maior, mas lazy-loaded).
- Nada de animação bloqueando o first input ou competindo com o carregamento crítico.
Perguntas: "Como você especifica uma animação para o dev?" (gatilho, propriedades de/para, duração, easing exato, delay/stagger, estados, reduced-motion, tokens — não "suave"), "Quando Lottie vs Rive vs código?", "Como você garante que o motion chega igual à intenção?" (alinhar viabilidade cedo, spec precisa, revisar no device real), "O que é Smart Animate e qual a limitação?".
✏️ Exercício 8 — Escreva a spec
Escreva a especificação de handoff completa para a transição "abrir bottom sheet ao tocar em um botão", pronta para um dev implementar sem perguntar nada.
Gabarito (uma boa resposta): Gatilho: tap no botão "Opções". Backdrop: opacity 0 → 0.4 (preto), 240ms, linear. Sheet: transform: translateY(100%) → translateY(0); spring (stiffness 300, damping 30, mass 1) — ou, se sem spring, 280ms cubic-bezier(0.2, 0, 0, 1). Conteúdo do sheet: aparece junto (sem stagger neste caso). Handle (a barrinha de arrastar): estática. Interrupção: se o usuário arrastar durante a entrada, a spring assume o gesto (translateY segue o dedo 1:1); ao soltar, snap para aberto (> 40% da altura ou velocidade para baixo < 0) ou fechado. Saída: translateY(0 → 100%), 200ms cubic-bezier(0.4, 0, 1, 1); backdrop opacity → 0 no mesmo tempo; ao terminar, remover do DOM. reduced-motion: sem translate — o sheet e o backdrop entram só com opacity (0 → 1) em 120ms; saída simétrica. Foco: mover o foco para o sheet ao abrir; devolver ao botão ao fechar. Tokens: --ease-emphasized-decelerate, --duration-md, --scrim-opacity.
Motion num design system
Objetivo: transformar timing, easing e padrões de transição em motion tokens e diretrizes — com prefers-reduced-motion como cidadão de primeira classe.
9.1 Motion tokens
:root{
/* durações */
--duration-instant: 50ms;
--duration-fast: 100ms; /* micro: hover, ripple */
--duration-sm: 150ms;
--duration-md: 250ms; /* transições de elemento */
--duration-lg: 350ms; /* painéis, telas */
--duration-xl: 500ms; /* momentos expressivos */
/* curvas — nomeadas por papel, não por valor */
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
--ease-decelerate: cubic-bezier(0, 0, 0, 1); /* entradas */
--ease-accelerate: cubic-bezier(0.3, 0, 1, 1); /* saídas */
--ease-emphasized: cubic-bezier(0.2, 0, 0, 1); /* momentos de destaque */
/* springs (para libs que aceitam) */
--spring-default: 300, 30, 1; /* stiffness, damping, mass */
}
- Papéis, não números soltos: um componente pede
--duration-md+--ease-decelerate, não237ms. - Productive vs expressive (modelo da IBM): motion productive (rápido, sóbrio, para tarefas repetidas) e expressive (mais longo, com caráter, para momentos-chave) — dois conjuntos de tokens.
- Integra com os outros tokens do design system (ver Design Systems & Design Tokens).
9.2 Padrões documentados
O design system não documenta só tokens — documenta quando usar cada transição: "menus e popovers usam scale a partir da origem + --duration-sm + --ease-decelerate"; "navegação entre telas usa slide horizontal + --duration-lg"; "listas usam fade + move de 8px com stagger de 30ms, máximo 8 itens". Assim o motion sai consistente entre times.
9.3 prefers-reduced-motion — de primeira classe
- Parte real da população tem desordens vestibulares; movimento (sobretudo grande, com parallax, zoom, rotação) causa tontura, náusea, dor de cabeça. Não é preferência estética.
- "Reduce" não é "remove tudo". A recomendação: troque animações de movimento (translate, scale grande, parallax) por animações de opacidade (fades) e transições instantâneas; mantenha feedback essencial (um spinner ainda gira; um estado ainda muda — só sem o "voo").
- Implementação: um utilitário/token que, sob a media query, zera durações de movimento ou substitui os keyframes.
@media (prefers-reduced-motion: reduce){
:root{ --duration-lg: 1ms; --duration-md: 1ms; }
.parallax{ transform: none !important; }
.slide-in{ animation-name: fade-in; } /* troca "voar" por "aparecer" */
}
9.4 WCAG e motion
- 2.2.2 Pause, Stop, Hide: qualquer movimento automático que dure > 5s e comece junto com outro conteúdo precisa de controle para pausar/parar (carrosséis, fundos animados).
- 2.3.1 Three Flashes: nada pisca mais de 3×/s em área significativa.
- 2.3.3 Animation from Interactions (AAA): movimento disparado por interação deve poder ser desativado — o que
prefers-reduced-motionatende. - Ver a apostila Acessibilidade Digital & WCAG.
9.5 Governança
- Lint: proibir durações/easings literais no código de componente (só tokens).
- Um "motion spec" por padrão no site do design system, com exemplos ao vivo e o comportamento reduced-motion lado a lado.
- Revisão de motion no checklist de PR de componente (tokens? reduced-motion? 60fps? interrompível?).
- Consistência cross-plataforma: as curvas e durações conceituais são as mesmas; a implementação usa o idioma de cada plataforma (Core Animation, Compose, CSS).
Toda vez que você especificar uma animação, escreva na mesma hora a variante reduce. Não é "acessibilidade que se adiciona no fim" — é metade da spec. Se a sua transição só "funciona" com um voo de 400px e não sobrevive a virar um fade, provavelmente ela estava dependendo do movimento para esconder um problema de layout ou de hierarquia.
Perguntas (design systems / design engineer): "O que são motion tokens?" (durações e curvas nomeadas por papel; productive vs expressive), "O que prefers-reduced-motion: reduce deve fazer?" (trocar movimento por opacidade/instantâneo, manter feedback essencial — não apagar tudo), "Que critérios da WCAG tocam motion?" (2.2.2, 2.3.1, 2.3.3), "Como você mantém motion consistente entre times/plataformas?" (tokens + padrões documentados + lint; curvas conceituais iguais, implementação nativa).
✏️ Exercício 9 — Tokenize e torne acessível
Para um design system, especifique: (a) 4 tokens de duração e 3 de easing, com o papel de cada; (b) 3 padrões de transição documentados (menu, tela, lista); (c) a política de prefers-reduced-motion para cada um dos 3; (d) 2 regras de governança.
Gabarito (uma boa resposta): (a) --duration-fast 100ms (micro/hover), --duration-md 200ms (elemento), --duration-lg 320ms (painel/tela), --duration-xl 500ms (expressivo); --ease-decelerate (entradas), --ease-accelerate (saídas), --ease-standard (mover algo visível). (b) Menu/popover: scale 0.96→1 a partir da origem + fade, --duration-fast, --ease-decelerate. Tela: slide horizontal 100%→0 (direção = avançar/voltar), --duration-lg, --ease-standard, com shared element no header quando houver. Lista: fade + translateY 8px→0, stagger 30ms, máx. 8 itens, --duration-md. (c) Menu: mantém o fade, remove o scale/translate → só opacidade em --duration-fast. Tela: remove o slide → crossfade em --duration-md. Lista: remove o translate e o stagger → itens aparecem juntos com um fade curto. (d) lint proíbe transition/animation com tempo literal fora dos tokens; todo componente novo precisa da spec de motion + variante reduced-motion + verificação de 60fps no PR.
Mercado de trabalho: roadmap, entrevistas e portfólio
Objetivo: converter o conteúdo dos módulos em contratação — os cargos, um plano de estudo, um banco de perguntas e projetos que geram entrevista.
10.1 Onde motion de interface pesa
- Motion designer / UX motion: foca em animação de produto — transições, micro-interações, o sistema de motion.
- Interaction designer: o comportamento da UI, incluindo o tempo e a resposta.
- Design engineer / design technologist: implementa o motion com performance e o mantém no design system.
- Product designer: espera-se cada vez mais que especifique motion, não só telas estáticas.
- Design systems: os motion tokens, os padrões, a governança, o reduced-motion.
10.2 Roadmap de estudo (6–8 semanas)
| Semanas | Foco | Prática |
|---|---|---|
| 1 | Funções, custo, princípios (Módulos 1–2) | Gravar a tela de 3 apps; para cada animação, dizer a função ou marcar como decoração |
| 2 | Timing e easing (Módulo 3) | Recriar 5 transições variando duração/curva; anotar o que muda a percepção; brincar com springs |
| 3 | Tipos de transição (Módulo 4) | Prototipar no Figma: fade, slide, scale, shared element, container transform, stagger |
| 4 | Coreografia (Módulo 5) | Storyboard + protótipo de uma transição de tela complexa (lista → detalhe) com hierarquia de movimento |
| 5 | Micro-interações (Módulo 6) | Projetar e prototipar 6: toggle, checkbox, input, like, pull-to-refresh, botão async |
| 6 | Web: técnica e performance (Módulo 7) | Implementar 3 delas em código (CSS + WAAPI + Framer Motion); medir 60fps no DevTools |
| 7 | Spec, handoff, tokens, a11y (Módulos 8–9) | Escrever specs de handoff; montar um mini sistema de motion tokens + reduced-motion |
| 8 | Portfólio | Publicar os estudos de caso com vídeos antes/depois e o raciocínio |
10.3 Banco de perguntas (com a resposta que aprova)
Júnior/pleno — "Para que serve animação numa interface?"
Orientar a atenção, mostrar causa e efeito, manter continuidade espacial (de onde veio, para onde vai), dar feedback de que a ação foi registrada, mascarar espera, e expressar a marca. Toda animação precisa de uma dessas funções; se não tem, é decoração — que atrasa e distrai.
Pleno — "Que duração e easing você usa para as transições de UI?"
100–200ms para micro-interações, 200–400ms para transições de elemento/tela; maior ou mais distante = mais tempo; saídas mais rápidas que entradas. ease-out ("fast out, slow in") para entradas, ease-in para saídas, ease-in-out para mover algo que permanece visível. linear quase nunca (só opacidade e spinner). Springs quando há gesto/interrupção.
Pleno — "Qual transição para abrir um detalhe a partir de um card, e por quê?"
Shared element ou container transform: o elemento que existe nas duas telas (a imagem, o título) persiste e se transforma em vez de sumir e reaparecer. Isso mantém a continuidade — o usuário nunca perde o objeto de vista — e comunica "isto abriu daqui".
Pleno/eng — "O que é barato animar na web?"
transform (translate/scale/rotate) e opacity — rodam no compositor sem recalcular layout nem repintar. width, height, top/left, margin, box-shadow disparam layout/paint a cada frame e causam jank. Para "animar largura", usa-se scaleX; para posição, translate; para sombra, cross-fade de camadas. FLIP para mudanças de layout.
Sénior — "Como você especifica motion para um dev?"
Gatilho, propriedades com valores de/para, duração, easing exato (a cubic-bezier ou os parâmetros da spring), delay e stagger com ordem, estados inicial/final e o que acontece se interrompido, o comportamento sob prefers-reduced-motion, e a referência aos motion tokens. Mais um vídeo em câmera lenta ou o protótipo. "Suave" e "rápido" não são spec.
Sénior — "O que prefers-reduced-motion: reduce deve fazer?"
Não apagar toda animação. Trocar animações de movimento (translate, scale grande, parallax, rotação) por animações de opacidade ou transições instantâneas, mantendo o feedback essencial (um estado ainda muda, um spinner ainda gira). É uma questão de saúde — desordens vestibulares — não de gosto. Projeta-se a variante junto com a animação, não depois.
Sénior — "Como manter motion consistente num produto grande?"
Motion tokens (durações e curvas nomeadas por papel; productive vs expressive), padrões de transição documentados no design system (qual transição para menu, tela, lista, com os tokens), lint proibindo tempos literais, revisão de motion no PR (tokens, reduced-motion, 60fps, interrompível), e — cross-plataforma — as mesmas curvas/durações conceituais implementadas no idioma de cada plataforma.
Armadilha — "Adicionei umas animações para dar vida"
Animação sem função é dívida: atrasa tarefas repetidas, distrai, causa desconforto em quem tem sensibilidade vestibular, e envelhece mal. "Dar vida" não é um propósito. Cada movimento precisa informar algo — origem, mudança, feedback — e ter uma variante reduced-motion. Menos, mais curto, mais consistente.
10.4 Projetos de portfólio que geram entrevista
- Sistema de motion (âncora): motion tokens (durações, curvas, productive/expressive), padrões de transição documentados, reduced-motion, e 3–4 componentes usando tudo — como uma página de design system.
- Redesign de transições de um app real: escolha um app com motion fraco ou ausente, refaça as 4–5 transições principais, publique vídeos antes/depois com o raciocínio (função, timing, coreografia).
- Set de micro-interações: 6–8 micro-interações projetadas e implementadas em código, com a anatomia (trigger/rules/feedback/modes) e o caminho de erro documentados.
- Estudo de performance: a mesma animação implementada de forma ingênua (jank) e otimizada (compositor/FLIP), com as gravações do DevTools mostrando os frames.
- Estudo de reduced-motion: as mesmas transições com a variante acessível lado a lado, e uma nota sobre as decisões.
10.5 Fontes para continuar
- Livros: The Illusion of Life (Johnston & Thomas — os 12 princípios); Designing Interface Animation (Val Head); Microinteractions (Dan Saffer); Animation at Work (Rachel Nabors).
- Guidelines: Material Design — Motion; Apple HIG — Motion; IBM Design Language — Motion (productive/expressive); Fluent e Carbon motion.
- Web: web.dev e MDN sobre animações, View Transitions e scroll-driven; animations.dev (Emil Kowalski); a documentação do Framer Motion / Motion One / GSAP; cubic-bezier.com, easings.net.
- Referência de estudo: as seções de motion dos design systems públicos; coleções como UI Movement, Mobbin (para observar padrões reais).
- Nesta trilha: CSS Avançado: Animações & SVG (implementação), Design Systems & Design Tokens, Iconografia, Cor, Layout, Grade & Espaçamento, Acessibilidade Digital & WCAG, Figma, 3D em Tempo Real & Motion Graphics para Web.
Cinco ideias sustentam o motion de interface: (1) movimento com propósito — se não informa origem, mudança ou feedback, corta; (2) timing e easing definem tudo — curto, ease-out para entrar, saídas mais rápidas, springs para gestos; (3) continuidade — o que existe antes e depois persiste e se transforma, nunca some e reaparece; (4) na web, anime transform e opacity, meça 60fps, use View Transitions/FLIP; (5) motion tokens + prefers-reduced-motion projetados juntos fazem o movimento virar sistema — consistente e acessível.