Controle mais refinado sobre transformações CSS com propriedades de transformação individuais

Transformar elementos com as propriedades translate, rotate e scale

A propriedade transform do CSS

Para aplicar transformações a um elemento, use a propriedade transform do CSS. A propriedade aceita uma ou mais <transform-function>s, que são aplicadas uma após a outra.

.target {
  transform: translateX(50%) rotate(30deg) scale(1.2);
}

O elemento segmentado é transladado em 50% no eixo X, girado em 30 graus e, por fim, dimensionado para até 120%.

Embora a propriedade transform funcione bem, ela se torna um pouco tediosa quando você quer mudar qualquer um desses valores individualmente.

Para alterar a escala ao passar o cursor, você precisa duplicar todas as funções na propriedade de transformação, mesmo que os valores delas permaneçam inalterados.

.target:hover {
  transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}

As propriedades de transformação individuais

Os envios com o Chrome 104 são propriedades individuais para transformações CSS. As propriedades são scale, rotate e translate, que podem ser usadas para definir individualmente essas partes de uma transformação.

Ao fazer isso, o Chrome se junta ao Firefox e ao Safari, que já oferecem suporte a essas propriedades.

Compatibilidade com navegadores

  • 104
  • 104
  • 72
  • 14.1

Origem

Ao reescrever o exemplo transform anterior com as propriedades individuais, seu snippet ficará assim:

.target {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

A ordem é importante

Uma diferença importante entre a propriedade CSS transform original e as novas propriedades é a ordem em que as transformações declaradas são aplicadas.

Com transform, as funções de transformação são aplicadas na ordem em que são escritas, da esquerda (fora) para a direita (dentro).

Com as propriedades de transformação individuais, a ordem não é a ordem em que elas são declaradas. A ordem é sempre a mesma: primeiro translate (fora), depois rotate e depois scale (dentro).

Isso significa que os dois snippets de código a seguir dão o mesmo resultado:

.transform--individual {
  translate: 50% 0;
  rotate: 30deg;
  scale: 1.2;
}

.transform--individual-alt {
  rotate: 30deg;
  translate: 50% 0;
  scale: 1.2;
}

Em ambos os casos, os elementos segmentados serão primeiro convertidos por 50% no eixo X, depois girados por 30deg e, por fim, dimensionados por 1.2.

Se uma das propriedades de transformação individuais for declarada com uma propriedade transform, as transformações individuais serão aplicadas primeiro (translate, rotate e, em seguida, scale) com a transform por último (dentro). Mais detalhes estão na especificação que define como a matriz de transformação deve ser calculada.

Animações

O principal motivo para essas propriedades foram adicionadas é facilitar as animações. Digamos que você queira animar um elemento da seguinte maneira:

Gráfico de frames-chave.

Como usar o transform

Para implementar essa animação usando transform, seria necessário calcular todos os valores intermediários para todas as transformações definidas e incluí-los em cada frame-chave. Por exemplo, para fazer uma rotação na marca de 10%, os valores das outras transformações também precisam ser calculados, porque a propriedade transform precisa de todas elas.

Gráfico de frames-chave com valores intermediários calculados.

O código CSS resultante será este:

@keyframes anim {
  0% { transform: translateX(0%); }
  5% { transform: translateX(5%) rotate(90deg) scale(1.2); }
  10% { transform: translateX(10%) rotate(180deg) scale(1.2); }
  90% { transform: translateX(90%) rotate(180deg) scale(1.2); }
  95% { transform: translateX(95%) rotate(270deg) scale(1.2); }
  100% { transform: translateX(100%) rotate(360deg); }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

Como usar propriedades de transformação individuais

Com propriedades de transformação individuais, isso fica muito mais fácil de escrever. Em vez de arrastar todas as transformações de um frame-chave para outro, é possível segmentar cada transformação individualmente. Você também não precisa mais calcular todos esses valores intermediários.

@keyframes anim {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }

  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }

  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: anim 2s;
  animation-fill-mode: forwards;
}

Como usar propriedades de transformação individuais e vários frames-chave

Para tornar seu código modular, é possível dividir cada subanimação no próprio conjunto de frames-chave.

@keyframes move {
  0% { translate: 0% 0; }
  100% { translate: 100% 0; }
}

@keyframes scale {
  0%, 100% { scale: 1; }
  5%, 95% { scale: 1.2; }
}

@keyframes rotate {
  0% { rotate: 0deg; }
  10%, 90% { rotate: 180deg; }
  100% { rotate: 360deg; }
}

.target {
  animation: move 2s, scale 2s, rotate 2s;
  animation-fill-mode: forwards;
}

Graças a essa divisão, é possível aplicar cada conjunto separado de frames-chave como quiser, porque as propriedades transform, que agora se tornaram propriedades individuais, não se sobrepõem mais umas às outras. Acima disso, é possível dar um tempo diferente para cada transformação sem precisar reescrever tudo.

Desempenho

As animações que usam essas novas propriedades são tão eficientes quanto as animações da propriedade transform existente.

As animações de translate, rotate e scale são executadas no compositor da mesma forma que as animações do transform. Por isso, elas são boas para desempenho de animação da mesma forma que transform.

Essas novas propriedades também funcionam com a propriedade will-change. Em geral, é melhor evitar o uso excessivo de will-change com o número mínimo de elementos necessários e pelo menor tempo possível. Mas também é bom ser o mais específico possível. Por exemplo, se você estiver usando will-change para otimizar uma animação com as propriedades rotate e filter, declare isso usando will-change: rotate, filter. Isso é um pouco melhor do que usar will-change: transform, filter em um caso em que você está animando rotate e filter, porque algumas das estruturas de dados que o Chrome cria com antecedência quando você usa will-change são diferentes para transform e rotate.

Parte da série Newly interoperável (em inglês)