Animações em página inteira usando CSS

O Internet Explorer 9 introduziu o suporte ao CSS 2D Transforms. O Internet Explorer 10 Developer Preview adicionou suporte ao CSS 3D Transforms e ao CSS Animations. Ao ligar a sua GPU e executar assincronamente de um JavaScript comum, esses recursos do IE10 fornecem uma alternativa mais segura e flexível do que as animações tradicionais baseadas em script para um conteúdo Web.

Em postagens anteriores do blog, falamos de CSS 3D Transforms e também de CSS Animations e Transitions. Nesta postagem, introduziremos um caso de uso “não convencional” dessas tecnologias ao descrevermos o conceito de “animações em página inteira”, que pode ser usado durante o processo de navegação para adicionar fluidez e continuidade à navegação. Nosso objetivo é criar uma experiência de navegação mais fluida na qual o conteúdo surge suavemente para ser exibido quando o usuário visita uma página e sai da exibição quando o usuário clica em um link ou realiza alguma ação relevante.

Esses efeitos podem ser obtidos ao transformar o elemento HTML <body> usando CSS Animations. No entanto, esse caso apresenta algumas considerações que achávamos que mereciam ser discutidas, como o efeito do layout e do tamanho durante a transformação de <body>, assim como a marcação correta do tempo das navegações das páginas para que eles mesclem adequadamente com nossas animações.

Os exemplos de códigos nesta postagem utilizam marcação CSS sem prefixos de acordo com o suporte do IE10 Release Preview. Outros navegadores devem solicitar prefixos de fornecedores para as propriedades CSS Animations e CSS Transforms usadas.

Transformando o conteúdo completo de uma página

Os CSS Transforms são definidos com base nas propriedades estilísticas de um elemento HTML DOM. Por exemplo, a marcação para o giro de 45 graus de um elemento ao longo de seu próprio eixo Z seria assim:

#element {

transform: rotateZ(45deg);

}

Anexar um transform ao elemento <body> do seu documento HTML funciona exatamente da mesma maneira. Portanto, realizar uma ação para adicionar declarativamente o mesmo efeito ao <body> do seu documento, poderia ser feito desta maneira:

body {

transform: rotateZ(45deg);

}

Vejamos uma imagem antes e depois de uma página ao aplicarmos um código transfom ao elemento body:

Captura de tela mostrando a aplicação de rotateZ(45deg) transform ao elemento body de um documento
Aplicando rotateZ(45deg) transform ao elemento body de um documento.

Para transformações de três dimensões, a especificação CSS Transforms define a propriedade perspective que pode ser especificada no pai do elemento que estamos transformando. Ao transformar o elemento <body> do seu conteúdo, ela deve ser aplicada ao elemento <html> que está acima dele na hierarquia DOM. Como fazer isso de maneira simplificada:

html {

perspective: 500px;

}

Combinando isso com um rotateY(45deg) transform no elemento <body> traz o seguinte resultado:

Captura de tela mostrando a aplicação de rotateY(45deg) transform em <body> com perspective: 500px definidos em <html>
Aplicação de rotateY(45deg) transform em <body> com perspective: 500px definidos no <html>.

Podemos manipular a propriedade do transform-origin no elemento body para obter resultados interessantes. Vejamos alguns exemplos:

body {

transform-origin: 50% 100%;

transform: rotateX(45deg);

}

A marcação acima define um giro no eixo X para o elemento body enquanto altera a origem dos giros para a parte inferior do elemento utilizando transform-origin. Isso proporcionará o giro do conteúdo do documento para “dentro” da tela da seguinte maneira:

Captura de tela mostrando a aplicação da transfom: rotateX(45deg) e transform-origin: 50% 100% para <body>

Também podemos manipular a propriedade perspective-origin no elemento raiz de nosso documento para alcançar um efeito de projeção para fora do eixo. Alterando o estilo de <html> para:

html {

perspective: 500px;

perspective-origin: 90% 50%;

}

Nossa página agora está assim:

Captura de tela mostrando a aplicação de perspective: 500px e perspective-origin: 90% 50% ao elemento <html>

Ao usar CSS Transforms, podemos facilmente manipular a aparência completa do conteúdo da página. Já que as regras comuns de layout e de tamanho ainda se aplicam, alguns transforms no elemento body (em particular aquelas que utilizam valores de porcentagem ou que dependem da propriedade transform-origin) podem resultar em efeitos visuais diferentes dependendo do conteúdo da nossa página. Basta lembrar de nosso exemplo rotateX(45deg) anterior com transform-origin definido para 50% 100%.

Abaixo, é possível observar os resultados antes e depois da aplicação do transform.

Captura de tela destacando a diferença nas barras de rolagem antes e depois da aplicação do transform na projeção em perspectiva

Observe como o conteúdo não se concentra na parte inferior da janela, e sim em um ponto determinado fora do visor. Isso é um comportamento esperado do CSS Transforms: o elemento <body> é detalhado normalmente e depois é girado ao longo de sua extremidade inferior que está em algum ponto fora da tela. Você também notará que o volume real do conteúdo foi expandido (dê uma olhada nas barras de rolagem na imagem “depois”) para acomodar o conteúdo transformado (o fato de estarmos utilizando projeção em perspectiva torna este efeito ainda mais pronunciado).

Portanto, como lidamos com um conteúdo de tamanho arbitrário ao aplicar transforms em nosso elemento body? A personalização de todo o conteúdo para assegurar que o tamanho de body não se expanda mais do que uma quantidade específica pode ser irreal. Em vez disso, podemos utilizar um padrão simples HTML/CSS que nos permita adaptar o tamanho do elemento body para o da janela do navegador e o conteúdo de acréscimo dentro de um wrapper<div>. A marcação a seguir produz exatamente isso:

html, body {

width: 100%;

height: 100%;

min-width: 100%;

max-width: 100%;

padding: 0;

margin: 0;

overflow: hidden;

}

 

#Wrapper {

position: absolute;

width: 100%;

height: 100%;

overflow: scroll;

}

A ilustração abaixo mostra o que ocorre quando uma página é exibida verticalmente e nós aplicamos rotateY(45deg) transform ao elemento <body> de nosso documento diretamente (esquerda) e utilizando o padrão wrapper (direita):

Captura de tela mostrando o que ocorre quando uma página é exibida verticalmente e rotateY(45deg) transform é aplicado ao elemento <body> em uma projeção em perspectiva, com e sem um padrão wrapper CSS/HTML

A aplicação direta do transform resulta em uma exibição inclinada devido à projeção fora do eixo (já que não estamos mais olhando o “centro” do elemento body). Ao utilizarmos um padrão wrapper nos asseguramos de que a propriedade perspective-origin do elemento <html> (50% 50% por padrão) seja sempre corretamente centralizada em relação ao elemento <body>, nos oferecendo assim um efeito visual agradável.

Ao utilizarmos o padrão acima e definirmos, sempre que possível, o CSS Transforms com valores de porcentagem, podemos afetar nosso elemento <body> de maneira consistente, independentemente do tamanho de seu conteúdo.

De Transforms à Animations

Tendo definido a complexidade da aplicação do CSS Transforms ao elemento <body>, o CSS Animations é o próximo passo. Ao seguir os princípios descritos acima, podemos criar animações que dão destaque (ou removem) da exibição o nosso conteúdo Web de maneiras interessantes.

Considere esta regra @keyframes básica:

@keyframes rotateInLeft {

from {

transform-origin: 0% 0%;

transform: rotateY(180deg);

}

to {

transform-origin: 0% 0%;

transform: rotateY(0deg);

}

}

Ao ser aplicada em um elemento, esta animação iniciará um giro do lado esquerdo. Ao ser aplicado em um elemento <body> que utiliza nosso padrão wrapper, o resultado visual é mais interessante. O documento fará o giro de fora da área visível da janela do navegador até ser exibido completamente:

Três capturas de tela em sequência mostrando o efeito da aplicação da animação

Semelhantemente, podemos compor animações que removem de maneira fluida o nosso conteúdo Web exibido. Por exemplo, se quiséssemos que nossa página desaparecesse ao fundo girando, poderíamos utilizar algo assim:

@keyframes whirlOut {

to {

transform: scale(0)rotateZ(1260deg);

}

}

E o resultado visual seria o seguinte:

Três capturas de tela em sequência mostrando o efeito da aplicação da animação

Já que podemos utilizar o todo o potencial do CSS Animations em nosso conteúdo Web, há bastante flexibilidade na geração desses efeitos de página (e certamente não estamos limitados ao uso do CSS Transforms). Após termos composto os efeitos que desejamos aplicar em nosso conteúdo, como fazemos para que eles sejam acionados durante o processo de navegação da página?

Anexando Animations ao <body>

Nossa meta é utilizar animações acionadas em momentos estratégicos durante a experiência de navegação para criar a aparência de transição de conteúdo para dentro da área de exibição quando a página for carregada e para fora da área de exibição quando o usuário clicar em um link.

O primeiro local intuitivo a adicionar uma animação ao elemento body seria o evento onload JavaScript. Ao que parece, no entanto, a adição de uma animação quando onload é disparado é tarde demais. Este evento na verdade é acionado quando o conteúdo completo em nossa página terminou de ser carregado (incluindo imagens ou outros recursos que exigem mais da largura de banda). Anexar uma animação a onload em uma página que exige muito da largura de banda resultaria em uma exibição “normal” de nosso conteúdo, seguido por um acionamento da animação que traria de volta o conteúdo para a área de exibição. E isso não é exatamente o efeito que estávamos buscando.

Como alternativa, poderíamos utilizar o evento DOMContentLoaded que é acionado quando o navegador conclui a análise da estrutura DOM de nosso conteúdo (mas possivelmente antes de os recursos terem concluído o carregamento). A demonstração DOMContentLoaded do ''test drive'' do IE ilustra a diferença entre esses dois eventos. No entanto, no caso de um conteúdo Web mais complexo, um navegador moderno pode escolher executar a renderização “progressiva”, exibindo a página antes de a árvore DOM ter sido completamente carregada. Nessas situações, o resultado visual seria semelhante ao cenário onload.

O local ideal para se definir uma animação que transforma o conteúdo em exibição na nossa página está embutido no topo do elemento <body>. Isso garante que a animação seja iniciada corretamente quando o conteúdo for renderizado (e que a posição inicial do conteúdo seja a do quadro chave from de nossa animação selecionada). Um efeito colateral positivo dessa abordagem é que a animação pode mascarar qualquer renderização progressiva, re-layout ou carregamento de recurso que possam ocorrer em um conteúdo complexo.

A configuração de animações que fazem a transição de nosso conteúdo para fora da exibição também é interessante. É possível presumir que poderíamos anexar um manipulador onclick em todos os elementos de interesse em nosso conteúdo (por exemplo, todas as marcas <a>) e simplesmente define as propriedades de animação relevantes (animation-name, animation-duration etc.) na função de retorno. No entanto, se não atrasarmos a navegação, não veremos a transição fluida esperada.

Esta é uma boa oportunidade para utilizarmos os eventos de animação descritos na especificação do CSS Animations. Especificamente, podemos utilizar o evento animationend para detectar quando a animação foi concluída e então acionar uma navegação (definindo window.location.href, por exemplo). E assim, onclick acionará a animação “remove-from-view” e registrará um manipulador para animationend em <body> que garantirá que o evento de navegação ocorra.

Demonstração online disponível

Criamos uma demonstração e um tutorial em inglês sobre como acrescentar dinamismo às páginas com CSS Transforms e Animations. A demonstração oferece mais informações e exemplos do que esses que conseguimos mostrar aqui. O próprio tutorial utiliza animações em página inteira que funcionam no Internet Explorer 10 no Windows 8, assim como nas versões recentes do Chrome e do Firefox.

Para aproveitar as animações de cada página, navegue pelas páginas do tutorial utilizando os links “Continue to ...” (Continuar para...) no canto inferior direito de cada página.

Ao fim do tutorial, fornecemos algumas orientações adicionais e um código de exemplo sobre como incorporar essas animações ao seu próprio conteúdo Web.

Conclusão

CSS Transforms e CSS Animations são dois conjuntos de recursos avançados que possibilitam experiências mais imersivas na Web. Esta postagem do blog descreveu algumas considerações sobre o uso de CSS Transforms e CSS Animations para que você possa acrescentar mais dinamismo em todo o seu conteúdo Web. Sem muito esforço, é possível criar páginas da Web (até mesmo páginas estáticas) que ofereçam uma experiência de navegação mais fluida e semelhante a dos aplicativos.

—Charilaos “Harris” Papadopoulos, estagiário de gerenciamento de programas, gráficos do Internet Explorer