Os efeitos de entrada e saída são animações acionadas quando um elemento entra ou sai da janela de visualização. Isso pode ser usado para criar experiências de usuário envolventes e dinâmicas. Por exemplo, você pode usar um efeito de entrada para fazer um elemento aparecer gradualmente ao rolar para a visualização ou um efeito de saída para reduzir o tamanho dele ao rolar para fora da visualização.
Como fazer a implementação
Para adicionar efeitos de entrada e saída a um elemento, é necessário combinar algumas propriedades CSS. Veja a seguir um guia passo-a-passo:
Crie
@keyframesseparados para as animações de entrada e saída. A animação de entrada será aplicada quando o elemento entrar na janela de visualização, e a de saída, quando ele sair.@keyframes slide-in { from { transform: translateX(-100%); } } @keyframes slide-out { to { transform: translateX(100%); } }Anexe os frames-chave de entrada e saída ao elemento. Para fazer isso, defina várias animações na propriedade
animation.- Dê à animação de entrada um
animation-fill-modedebackwardspara que ela aplique o estado inicial antes de começar. - Dê à animação de saída um
animation-fill-modedeforwardspara que ela mantenha o estado final após a conclusão.
.animated-element { animation: slide-in 1s linear backwards, slide-out 1s linear forwards; }- Dê à animação de entrada um
Crie uma linha do tempo de visualização e vincule-a às animações. Uma linha do tempo de visualização é um tipo de linha do tempo vinculada à visibilidade de um elemento na janela de visualização. Você pode criar um usando a função
view()e aplicá-lo às suas animações usando a propriedadeanimation-timeline..animated-element { animation-timeline: view(); }Por padrão,
view()rastreia o elemento no eixoblock. Se você precisar rastreá-lo no eixoinline, useview(inline).Limite as animações aos intervalos
entryeexit. A propriedadeanimation-rangepermite especificar em qual parte da linha do tempo uma animação deve ser executada.- O intervalo
entryabrange o tempo desde que o elemento entra na janela de visualização até que ele esteja totalmente visível. - O intervalo
exitabrange o tempo desde o momento em que o elemento começa a sair da janela de visualização até que ele fique completamente oculto.
.animated-element { animation-range: entry, exit; }- O intervalo
Exemplo de código
Este código anima os filhos diretos do scroller ao rolar usando uma linha do tempo de visualização anônima:
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: view(inline);
animation-range: entry, exit;
}
}
}
Quando os elementos entram na janela de rolagem, a animação grow é reproduzida. Quando eles saem, a animação shrink é reproduzida.
O código a seguir tem o mesmo resultado visual, mas anima os filhos diretos do scroller ao rolar usando uma linha do tempo de visualização nomeada:
@media (prefers-reduced-motion: no-preference) {
@supports ((animation-timeline: view()) and (animation-range: entry)) {
@keyframes grow {
from {
scale: 0.5;
}
}
@keyframes shrink {
to {
scale: 0.5;
}
}
.scroller > * {
view-timeline: --tl inline;
animation:
grow auto linear backwards,
shrink auto linear forwards;
animation-timeline: --tl;
animation-range: entry, exit;
}
}
}
Práticas recomendadas
Ao usar animações acionadas por rolagem, é importante seguir algumas práticas recomendadas para garantir uma experiência tranquila e acessível:
- FAÇA a detecção de recursos: nem todos os navegadores oferecem suporte a animações acionadas por rolagem. Use
@supports ((animation-timeline: view()) and (animation-range: entry))para verificar a compatibilidade e fornecer um substituto para navegadores que não oferecem suporte.- A verificação
(animation-range: entry)PRECISA ser incluída aqui para filtrar navegadores com suporte parcial. - NÃO use o pacote
scroll-timeline-polyfillpara a estratégia de substituição, porque ele não tem todos os recursos e tem muitos problemas conhecidos. - Se a animação for considerada apenas decorativa, opte pelo aprimoramento progressivo e NÃO forneça um substituto.
- A verificação
- RESPEITE as preferências do usuário: algumas pessoas preferem menos movimento na Web. Use a consulta de mídia
prefers-reduced-motionpara desativar ou reduzir as animações para esses usuários. - FAÇA o possível para animar apenas propriedades CSS de alto desempenho: para animações mais suaves, anime propriedades que podem ser processadas pela linha de execução do compositor do navegador, como
transformeopacity. Animar outras propriedades, comowidthouheight, pode causar problemas de desempenho. - RECOMENDADO: use a ordem de declaração correta. Ao usar a propriedade abreviada
animation, declareanimation-timelinedepois dela para evitar que a abreviação redefina a linha do tempo.
Ao usar a função view() para criar uma animação acionada por rolagem:
- OPCIONAL Seja explícito sobre o eixo a ser rastreado: quando não estiver segmentando o eixo
blockpadrão (como em um rolador horizontal), seja explícito sobre qual eixo rastrear comview(block)ouview(inline). - Quando a animação não é aplicada ao próprio objeto rastreado, use uma linha do tempo de visualização nomeada.
Ao usar a propriedade view-timeline para criar uma animação acionada por rolagem:
- USE um CSS
<dashed-ident>para o nome. - OPCIONAL: seja explícito sobre o eixo a ser rastreado. Quando não estiver segmentando o eixo
blockpadrão (como em um scroller horizontal), seja explícito sobre qual eixo rastrear comview-timeline-axis. - VERIFIQUE se o escopo da pesquisa funciona: quando o elemento que declara o
view-timelinenão é um ancestral de árvore simples do elemento animado, eleve a visibilidade do nome doview-timelineusandotimeline-scopeem um ancestral compartilhado.
Dê preferência a um view-timeline nomeado quando vários elementos ou filhos do objeto rastreado precisarem ser animados.
Suporte ao navegador e estratégias de substituição
Portanto, uma estratégia de fallback geralmente é necessária.
Para navegadores que não oferecem suporte a animações acionadas por rolagem, use um substituto para recriar os efeitos visuais. Os substitutos geralmente são criados com um listener de rolagem (para efeitos de ScrollTimeline) ou com a API IntersectionObserver (para efeitos de ViewTimeline).
Em navegadores com suporte integrado para animações de rolagem, use SEMPRE a implementação nativa de CSS, porque ela tem melhor desempenho.
Nem todos os efeitos podem ser recriados usando a abordagem de substitutos.
Para esse caso de uso específico, o script a seguir aplica o substituto para navegadores que não oferecem suporte a animações de rolagem. Ele usa um IntersectionObserver para rastrear a visibilidade do elemento .wrapper e atualiza a propriedade transform das camadas com base na posição de rolagem.
<script>
if (!CSS.supports('(animation-timeline: view()) and (animation-range: entry)')) {
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
// This matches the effect as defined in the CSS example above.
// Customize this further if needed.
entry.target.style.scale = 0.5 + entry.intersectionRatio * 0.5;
}
},
{
threshold: Array.from({ length: 101 }, (_, i) => i / 100),
}
);
document.querySelectorAll('.scroller > *').forEach((el) => {
observer.observe(el);
});
}
</script>