aller au contenu principal

Les nouvelles propriétés translate, scale et rotate

La fin de la propriété transform en CSS ?


Publié le 11/05/2023 dans Blog
Crédit photo - Unsplash - Milad FakurianCrédit photo : Unsplash - Milad Fakurian
Je suis en train d'écrire un cours complet sur Flexbox. Il y aura un module entier sur la compréhension de ce mode de layout, et un module 100% pratique avec plusieurs exercices.Tu peux consulter le programme et à te préinscrire dès maintenant ! ⬇️Se préinscrire

Dans cet article je te propose de te partager ce que j'ai appris sur les nouvelles propriétés de transformations individuelles translate, rotate et scale.

Ces nouvelles propriétés CSS sont les équivalents des fonctions translate(), rotate() et scale() qui s'utilisent avec la propriété transform.

Si ce sont des équivalents, pourquoi ces nouvelles propriétés, qu'apportent t-elles de nouveau, et que devient la propriété transform ?

Pour répondre à ces questions, il faut d'abord comprendre le problème que l'on peut rencontrer très souvent avec la propriété transform : la gestion de plusieurs fonctions de transformations sur un même élément ou dans une animation.

Mais avant, je te propose de voir un exemple avec des transformations faîtes avec la propriété transform, et leur équivalent avec ces nouvelles propriétés :

.element-1 {
  transform: scale(1.5);
}
.element-2 {
  transform: translate3d(50px, 100px, 200px);
}
.element-3 {
  transform: rotateY(90deg);
}

Maintenant les mêmes transformations, mais avec les propriétés translate, rotate et scale :

.element-1 {
  scale: 1.5;
}
.element-2 {
  translate: 50px 100px 200px;
}
.element-3 {
  rotate: y 90deg;
}

Cool non ? 😉

La propriété transform a disparu et le code est un peu plus concis.

Si tu sais faire des transformations CSS, ces propriétés devraient te paraître simple d'utilisation, même si cela peut être un poil déstabilisant si on est habitué depuis longtemps aux fonctions de transformations.

Maintenant, pour comprendre quel intérêt on peut trouver à ces 3 nouvelles propriétés, il faut aller un peu plus loin et prendre un exemple où il faut gérer plusieurs transformations sur un même élément.

Comme j'aime le faire, je vais partir d'un exemple très simple : le centrage vertical et horizontal d'un élément en position absolute :

.element {
  position: absolute;
  top: 50%;
  left: 50%;
}

Ici les propriétés top et left à 50% ne suffisent pas à vraiment centrer l'élément, c'est le coin supérieur gauche qui est positionné au centre.

Pour placer le centre de l'élément au centre de son parent, il faut le déplacer de sa moitié vers le haut et vers la gauche : la moitié de sa largeur vers la gauche et la moitié de sa hauteur vers le haut.

Pour faire cela, la fonction translate() est idéale :

🦁

😢 L'élément n'est pas complétement centré..
Pour le centrer, il faut le déplacer de sa moitié sur l'axe X et Y.
La fonction translate() est idéale pour cela, elle prend en paramètre la quantité de déplacement : le premier paramètre est pour l'axe X, le second pour l'axe Y.
Ne pas faire de transformation revient à faire un transform: translate(0, 0).

C'est une technique très connue et qui fonctionne très bien.

Maintenant ajoutons une nouvelle transformation en faisant faire une rotation à l'élément au survol de ce dernier :

.element {
  transform: translate(-50%, -50%);
  transition: transform .5s linear;
}
.element:hover {
  transform: rotate(45deg);
}

Avec le code ci-dessus, la rotation fonctionnera au survol de l'élément, sauf que préciser une seule transformation revient à mettre les valeurs par défaut des autres transformations, et c'est un problème car on a déjà définit un translate(-50%, -50%) sur l'élément.

Je m'explique : écrire un transform: rotate(45deg) revient à écrire transform: translate(0, 0) rotate(45deg), ce qui aura pour conséquence de déplacer l'élément au survol en le remettant dans son positionnement initial.

Pour régler cela, il faut aussi préciser un translate(-50%, -50%) au survol :

.element {
  transform: translate(-50%, -50%);
}
.element:hover {
  transform: translate(-50%, -50%) rotate(45deg);
}

On répète du code, mais c'est le seul moyen d'y parvenir.

Tu peux faire l'expérience toi même en passant ta souris sur l'élément :

🦁

😢 La rotation fonctionne mais le translate(-50%, -50%) a été perdu, et l'élément n'est plus centré au survol.
Faire un transform: rotate(45deg) revient à faire un transform: translate(0, 0) rotate(45deg).

Cela peut paraître bizarre mais c'est logique : on utilise la même propriété au survol, on écrase donc sa valeur initiale.

Pour cet exemple ce n'est pas très génant, mais ça peut le devenir si on doit le faire souvent.

Comme lorsqu'on doit faire des animations plus complexes comme des keyframes avec plusieurs transformations.

La solution : les propriétés de transformation individuelles

Il n'y aura pas le problème décrit juste avant avec les propriétés de transformation individuelles, puisque chacunes des transformations pourront être faîtes sur leur propriété.

Reprenons l'exemple précédent mais cette fois en utilisant la propriété translate et rotate plutôt que la propriété transform :

.element {
  translate: -50% -50%;
  transition: rotate .5s linear;
}
.element:hover {
  rotate: 45deg;
}

Nul besoin ici de modifier la propriété translate au survol, puisque c'est seulement la propriété rotate qui est ajoutée.

Des animations plus simples à écrire

Avec ces nouvelles propriétés, les animations seront aussi plus simple à écrire.

Si on prend comme exemple une animation construite avec un keyframe, on va voir que ces nouvelles propriétés vont non seulement nous permettre de rendre le code plus concis et plus lisible, mais aussi plus facilement éditable.

Partons de l'animation suivante, avec des transformations réalisées avec la propriété transform :

@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); }
}

Même si on est obligé d'écrire les transformations ainsi, cela fait beaucoup de code écrit pour "rien".

Par exemple pour la fonction translateX(), à part sur le 0% et le 100%, toutes les autres fonctions sont inutiles, mais on est obligé de les préciser.. On observe la même chose sur le rotate(180deg) et le scale(1.2).

Comparons maintenant avec la même animation, mais construite avec les propriétés translate, rotate et scale 🤩 :

@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; }
}

L'approche est différente comme tu peux le voir, le code est plus clair et il est facile de venir éditer les transformations sans se soucier de l'impact sur les autres.

Voici le résultat si on utilise le keyframe avec la propriété animation :

.element {
  animation: anim 2.5s linear 1s infinite alternate;
}
🦁

L'ordre a son importance

Je profite de cet article pour te partager quelque chose que j'ai appris il y a peu : l'ordre des fonctions de transformation sur la propriété transform a une importance.

Le code ci-dessous ne produira pas le même résultat :

.element-1 {
  transform: rotate(90deg) translateX(50%);
}
.element-2 {
  transform: translateX(50%) rotate(90deg);
}

En effet, le positionnement des éléménts sera complétement différent.

C'est normal, les fonctions sont lues de la gauche vers la droite.

Je te propose encore une fois de visualiser les choses pour bien comprendre : avec un transform: translateX(50%) rotate(90deg); :

🦁

Avec un transform: rotate(90deg) translateX(50%); :

🦁

Est-ce qu'on aura ce comportement avec les propriété de transformation individuelles ? Non.

L'ordre sera toujours celui-ci : translate, rotate puis scale.

C'est pour cette raison que le code suivant produira le même résultat :

.transform-1 {
  translate: 50% 0;
  rotate: 90deg;
  scale: 1.2;
}

.transform-2 {
  rotate: 90deg;
  translate: 50% 0;
  scale: 1.2;
}

Donc est-ce que l'arrivée des propriétés de transformation individuelles sonne la fin de la propriété transform ?

Surtout pas ! La propriété transform reste utile, certaines transformations ne sont pas possible avec les propriétés individuelles car l'ordre des transformations est préétabli et on ne peut pas le changer.

Un exemple avec cette transformation qui ne peut pas être réalisée avec les propriétés individuelles :

.element {
  transform: rotate(90deg) translateX(50%);
}

On peut essayer de le faire en CSS en mettant en premier la propriété rotate, cela ne changera rien :

.element {
  rotate: 90deg;
  translate: 50% 0;
}

D'abord l'élément sera déplacé de sa moitité sur l'axe X, puis en même temps qu'il se déplace il fera une rotation de 90 degrés, et comme on l'a vu plus haut, cela ne donne pas le même résultat si l'élément fait une rotation avant d'être déplacé.

Les unités sont obligatoires

Avec les propriétés translate, rotate et scale, il faudra toujours préciser l'unité, contrairement aux fonctions de transformations.

Par exemple il est possible de faire un rotate(0), mais un rotate: 0 ne fonctionnera pas.

Il faut préciser l'unité deg :

.element {
  rotate: 90deg;
}

.element:hover {
  /* ❌ Il n'y aura pas de rotation car il n'y a pas d'unité */
  rotate: 0;

  /* ✅ La rotation fonctionnera car l'unité "deg" est utilisée */
  rotate: 0deg;
}

Cependant passer d'un rotate: 0 à un rotate: 90deg fonctionnera.

Que devient transform-origin ?

C'est une question légitime, est-ce que la propriété transform-origin fonctionne toujours avec ces propriétés de transformations individuelles ?

La réponse est oui, le fonctionnement de cette propriété reste identique.

Pour rappel transform-origin permet de modifier le positionnement du point d'origine de transformation.

Niveau support des navigateurs, ça donne quoi ?

À à l'heure où j'écris ces lignes (le 4 mai 2023), le support est au rendez-vous avec plus 90% des navigateurs qui prennent en charge ces nouvelles propriétés !

Performances

Comme pour la propriété transform, les propriétés translate, rotate et scale s'exécutent sur le compositor thread du navigateur. Ces propriétés sont donc optimales pour les animations.

Tout comme transform-origin, les propriétés de transformation individuelles fonctionnent également avec la propriété will-change.

Cependant, les mêmes considérations lors de l'utilisation de will-change doivent toujours être suivies, telles que l'application de la propriété uniquement si l'animation ou la transformation provoque des problèmes de performances.

J'ai écris un article sur le sujet des performances lorsqu'on fait des animations CSS si tu veux aller plus loin sur ce sujet : Optimiser ses animations CSS.


Pour conclure, ces nouvelles propriétés ne remplaceront pas la propriété transform. Elles nous facilitent les choses lorsqu'on a besoin d'écrire des animations.

Je te remercie de m'avoir lu, n'hésites pas à me donner ton avis sur Twitter ou Linkedin !

Si tu souhaites être prévenu de la sortie des prochains articles et contenu du site, tu trouveras le formulaire d'inscription à ma newsletter un peu plus bas.

À bientôt, Seb.

D'autres articles qui peuvent t'intérésser :

2024 Sébastien Imbert