CSS Transform'ers 2D Interativo – Loop Infinito
Há pouco tempo li o excelente livro CSS Transforms: An Interactive Guide escrito pela Vicki Murley, uma evangelista web ex-Apple. Esta foi uma das melhores e mais fáceis leituras que já fiz relacionado a CSS. Além de tratar com muito domínio sobre o assunto, o que mais me chamou atenção foi o modo como é demonstrado cada nova função, tornando um assunto por vezes muito abstrato em algo prático e fácil de ser entendido.
Então, fortemente inspirado em seu livro, vou agora tentar explicar CSS Transforms de um modo similar ao modo que Vicki aborda em seu livro e, também, da mesma forma que sempre tentamos fazer por aqui: na prática.
Com o lançamento do primeiro iPhone em 2007, seu rápido ganho em popularidade e sua falta de suporte ao Adobe Flash, ficou claro que era necessário uma tecnologia web nativa — sem plug-ins de terceiros — para animações mais avançadas e de alta performance. Então, no mesmo ano de 2007, um engenheiro da Apple enviou para a mailing list da W3C a proposta para CSS Transforms. Esta especificação foi primeiramente implementada no WebKit, pois era de interesse da Apple, mas foi ganhando popularidade aos poucos, por se mostrar uma tecnologia mais performática, livre e cross-browser.
Hoje o CSS Transforms já está implementado em todos os grandes navegadores e seu uso em produção é bem comum e, inclusive, aconselhado. Ele torna possível adicionarmos efeitos visuais à web que antes só podiam ser implementados através de plug-ins de terceiros. Também servem de base para animações mais complexas e podem ser aplicados em qualquer elemento HTML. E são eles que vamos estudar e experimentar na prática como funcionam.
A função translate é usada para movermos um elemento nos eixos X, Y, ou ambos. Caso seja passado apenas um parâmetro para a função, o elemento será movido em relação ao eixo X. Já com dois parâmetros, o primeiro será o valor usado para a movimentação no eixo X, e o segundo para o eixo Y.
transform: translate(13px, 10px); /* move elemento 13px em X e 10px em Y */
transform: translate(13px); /* move elemento 13px no eixo X */
transform: translateX(13px); /* move elemento 13px no eixo X */
transform: translateY(10px); /* move elemento 10px no eixo Y */
Além de px, também podemos passar valores expressos em %. Neste caso, 100% será equivalente a dimensão do elemento no eixo em que vamos efetuar o translate. Em outras palavras: se vamos movimentar o elemento no eixo X, 100% será igual a sua largura; se a movimentação ocorrer no eixo Y, 100% equivalerá a altura do elemento. No experimento abaixo vocês podem ver a função translate em ação de uma forma mais interativa e menos abstrata, basta mover os handlers dos inputs do Translate X e Translate Y.
Reparem que valores negativos também são aceitos. Valores negativos em X movimentam o elemento para a esquerda. Valores negativos em Y movimentam o elemento para cima. Um transform: translateX(-10px); moverá o elemento 10 pixels para a esquerda. Enquanto um transform: translateY(-5px); moverá o elemento 5 pixels para cima.
A função skew irá "entortar" um elemento em relação a um dos eixos.
transform: skewX(30deg); /* "entorta" o elemento horizontalmente */
transform: skewY(30deg); /* "entorta" o elemento verticalmente */
As funções usadas para efetuarmos o skew são skewX e skewY. Cada uma recebe apenas um parâmetro, estes expressos em graus (deg). No experimento abaixo fica bem mais fácil entender o que acontece quando aplicamos o skew. Assim como no experimento acima, basta mover os handlers da parte esquerda inferior para alterar os valores e ver o efeito desta mudança na direita.
Também existe uma função skew, que, na teoria, funcionaria como um atalho para as funções skewX e skewY. Mas o seu resultado final não é o mesmo que o das funções skewX e skewY usadas de forma separada com os mesmos parâmetros de skew. O próprio MDN desaconselha seu uso.
A função rotate … rotaciona. Simples assim. Ela recebe um único parâmetro que pode ser expresso em graus (deg), radianos (rad) ou voltas (turn).
transform: rotate(30deg); /* rotaciona 30' no sentido horário */
transform: rotate(-45deg); /* rotaciona 45' no sentido anti-horário */
transform: rotate(2rad); /* rotaciona ~ 144,59' no sentido horário */
transform: rotate(0.5turn); /* rotaciona meia-volta no sentido horário */
Valores positivos rotacionam o elemento no sentido horário, enquanto que valores negativos rotacionam o elemento no sentido anti-horário. O experimento abaixo mostra o rotate em ação.
Altera o tamanho do elemento em ambos os eixos ou apenas em um eixo específico. Esta função aceita um ou dois parâmetros. Caso seja passado apenas um, a alteração irá ocorrer tanto na altura como na largura. Caso sejam passados dois, o primeiro argumento irá alterar a largura e o segundo irá alterar a altura.
Os valores passados como parâmetros não possuem unidades. Eles funcionam como "multiplicadores" do tamanho do elemento. Um transform: scale(2) irá duplicar o tamanho do elemento. Um transform: scale(0.5) irá reduzi-lo pela metade.
transform: scale(2); /* dobra o tamanho do elemento em todas as direções */
transform: scale(2, 3); /* dobra a largura e triplica a altura */
transform: scaleX(0.5); /* reduz largura do elemento pela metade */
transform: scaleY(2); /* deixa o elemento duas vezes mais alto */
Além da função scale, podemos usar as funções específicas de cada eixo: para o eixo X a scaleX e para o eixo Y a scaleY. Abaixo também podemos interagir com esta função e ver na prática como se comporta.
Observem no experimento acima que, ao passarmos valores negativos, nós invertemos a imagem. Se passarmos um valor de -1 para scaleX, é como se estivéssemos espelhando o elemento. -1 para scaleY e o elemento irá ficar de cabeça para baixo (invertido na vertical).
É possível usar várias funções transform ao mesmo tempo em um elemento. Para isso, é só declarar todas as funções — com seus devidos valores — separados por um espaço.
transform: skewX(45deg); /* sobrescreve a transformação acima */
transform: rotate(0.5turn) scale(2); /* rotaciona em 180º e duplica o tamanho */
Cuidado para não declarar várias regras transform no mesmo elemento, pois dessa forma a última regra sobrescreve todas as outras declaradas
transform 4 -webkit- 3.1 -webkit- 3.5 9.0 10.5 -webkit-
Com a exceção do Internet Explorer (alguém surpreso?), o CSS Transform já é suportado nos principais browsers há muito tempo. O IE só veio dar suporte na sua versão 9.0.
E para quem quiser se aprofundar mais no assunto, aconselho fortemente que comprem o livro CSS Transforms: An Interactive Guide da Vicki Murley. Nele, além de CSS Transforms 2D, também é abordado o assunto CSS Transforms 3D.
O código de todos os experimentos acima estão, como de costume, disponíveis no Github. Gostou? Dá uma estrela pro projeto =).