Transform
nous permet de créer une multitude d'effets de mouvement : nous pouvons absolument tout faire…
Sauf un mouvement de balancier…
Ou changer d’échelle du haut vers le bas… 🙃
Mais comme toujours en CSS, il y a une solution !
Découvrez le point d'ancrage
Par défaut, toutes les fonctions de transform
partent du centre de l’élément. Donc quand on change l’échelle d’un objet, il s’agrandit vers l’extérieur :
Et quand on fait pivoter un élément, il reste sur son axe :
Et souvent, c’est très bien. Mais parfois, ça ne suffit pas.
La propriété transform-origin
est là pour ça ! Elle permet de déplacer un point d’ancrage où on veut, pour faire partir nos animations de ce point.
Nous pouvons par exemple déplacer le point d’origine d'un élément à son sommet et le faire grandir :
Nous pouvons mettre le point dans un coin et faire balancer l’objet :
Dans ce chapitre, allons apprendre à maîtriser la propriété transform-origin
pour apprendre à faire tout cela. C'est parti !
Déplacez le centre
C'est à nouveau la propriété transform
qui sera notre alliée ici.
Créons donc une barre de chargement, avec une image vide qui se remplit pendant le chargement : sa progression ne correspond pas réellement au pourcentage de chargement, mais sert de transition entre deux blocs de contenu.
<div class="container">
<div class="btn">Charger!</div>
<div class="progress">
<div class="progress__bar"></div>
</div>
</div>
Nous avons stylisé l’image avec une bordure et un peu de marge intérieure, et la barre avec une couleur de fond, qui s’affiche comme ça :
Maintenant, ajoutons la propriété transform
à notre barre, et servons-nous de la fonction scaleX qui nous est déjà familière sur 0 :
.progress {
&__bar {
transform: scaleX(0);
}
}
Et voilà notre barre de progression vide !
Nous pouvons utiliser le pseudosélecteur :active
pour la remplir afin d'agrandir la barre à 100 % de largeur quand on clique sur le bouton “Charger”.
.btn {
&:active {
& + .progress {
& > .progress__bar {
transform: scaleX(1);
}
}
}
}
.progress {
&__bar {
transform: scaleX(0);
}
}
Maintenant, quand on clique sur le bouton, la barre de chargement se remplit… immédiatement.
Mais nous sommes dans un cours d'animation ici ! Nous voulons donc remplir la barre petit à petit. Pour cela, ajoutons donc une transition, en l’animant sur une durée de 2 secondes :
.btn {
&:active {
& + .progress {
& > .progress__bar {
transform: scaleX(1);
}
}
}
}
.progress {
&__bar {
transform: scaleX(0);
transition: transform 2000ms;
}
}
Voyons voir comment notre barre se comporte maintenant :
Heuuuu, ce n'est pas exactement l'effet que nous recherchions. Quoique, on va peut-être lancer une nouvelle mode ? 😏
Les barres de chargement se remplissent normalement depuis la gauche vers la droite. Ici, la barre se remplit, mais en partant du milieu. Pour corriger notre barre, nous pouvons maintenant tester la propriété transform-origin
.
transform-origin
nous permet de déplacer le centre d'origine de notre transformation, selon les valeurs que nous lui assignons.
Pour déplacer le centre d’origine, on peut utiliser des unités comme les pixels, ou un pourcentage des dimensions d’un élément, de la même manière que pour la fonction translate
. Dans les deux cas, l’axe X est mesuré à partir de la bordure gauche de l’élément, et l’axe Y est mesuré depuis le bord supérieur.
Le point d’origine par défaut, au centre de l’élément, peut donc être écrit de cette manière : transform-origin: 50% 50%
;
Ici, nous voulons placer le point d’origine de notre barre de chargement sur sa bordure gauche, pour qu’elle progresse vers la droite. Nous devons donc mettre l'origine de x à 0 % :
.btn {
&:active {
& + .progress {
& > .progress__bar {
transform: scaleX(1);
}
}
}
}
.progress {
&__bar {
transform-origin: 0% 50%;
transform: scaleX(0);
transition: transform 1000ms;
}
}
On devrait voir la barre être vide au départ. Puis au clic sur le bouton, elle devrait s’agrandir vers la droite jusqu’à remplir le cadre :
Parfait ! Mettons notre touche finale en ajoutant notre propre fonction de timing cubic-bezier()
. Nous voulons que la barre commence avec un ease-in peu prononcé, mais que son ease-out soit bien perceptible à la fin. Le profil de la courbe ressemblerait à quelque chose comme ça :
Les valeurs de notre courbe d’accélération sont cubic-bezier(.32, 0, .07, 1)
. Rentrons-les dans notre fonction de timing :
.btn {
&:active {
& + .progress {
& > .progress__bar {
transform: scaleX(1);
}
}
}
}
.progress {
&__bar {
transform-origin: 0% 50%;
transform: scaleX(0);
transition: transform 1000ms cubic-bezier(.32,0,.07,1);
}
}
Et c'est encore une réussite pour vous ! Bravo !💪
Utilisez la bonne valeur
Les valeurs de transform-origin
ne se limitent pas à des longueurs ou des pourcentages.
On peut aussi utiliser des mots clés CSS pour définir les points d’ancrage, comme left
pour le mettre sur le bord gauche, ou right
pour le mettre à droite :
.box--left-origin {
// positionne l'origine du côté gauche
transform-origin: left 50%;
}
.box--right-origin {
// positionne l'origine du côté droit
transform-origin: right 50%;
}
On peut aussi utiliser top
et bottom
:
.box--top-origin {
// positionne l'origine au sommet de l'élément
transform-origin: 50% top;
}
.box--bottom-origin {
// positionne l'origine en bas de l'élément
transform-origin: 50% bottom;
}
Concrètement, les mots clés left
et top
correspondent à 0 %, tandis que right
et bottom
correspondent à 100 %. Mais l'utilisation de ces mots clés permet d'être explicite dans la manière d'écrire notre code.
Le dernier mot clé est center
. Il peut être assigné à l’axe X ou Y, et correspond à une valeur de 50 :
.box--left-origin {
// positionne l'origine au centre de l'élément
transform-origin: center center;
}
Jusqu’à maintenant, nous avons toujours assigné deux valeurs à transform-origin
, une pour X et l’autre pour Y. Mais une seule valeur peut aussi suffire. Si cette valeur est un nombre, elle s’appliquera à l’axe X et laissera Y à la valeur par défaut de 50 %.
Dans le cas de notre barre de progression, c'est surtout la valeur de X qui nous intéresse. La valeur de 50 % pour l’axe Y est donc superflue. Retirons cette valeur, ce qui simplifie le code et montre plus explicitement que nous modifions l'axe X quand nous relirons le code dans le futur :
.btn {
&:active {
& + .progress {
& > .progress__bar {
transform: scaleX(1);
}
}
}
}
.progress {
&__bar {
transform-origin: 0%;
transform: scaleX(0);
transition: transform 1000ms cubic-bezier(.32,0,.07,1);
}
}
Notre code est plus propre et fonctionne toujours de la même manière dans le navigateur :
Et le navigateur n'a pas fini de nous étonner : si on assigne un simple mot clé à transform-origin
, le navigateur va comprendre de lui-même à quel axe l’appliquer, et laisser l’autre axe sur sa valeur par défaut.
Il est plus explicite d’utiliser le mot clé left
plutôt que de mettre un transform-origin
à 0 %, car cela nous indique instantanément que nous avons déplacé le transform-origin
sur le côté gauche. Revenons une dernière fois à notre barre de chargement et remplaçons la valeur numérique de transform-origin
par le mot clé left
, pour rendre notre code aussi clair et concis que possible :
.btn {
&:active {
& + .progress {
& > .progress__bar {
transform: scaleX(1);
}
}
}
}
.progress {
&__bar {
transform-origin: left;
transform: scaleX(0);
transition: transform 1000ms cubic-bezier(.32,0,.07,1);
}
}
Passez dans la troisième dimension
Nous avons vu que la propriété transform
permet de manipuler des éléments en deux dimensions... mais aussi en trois. Et transform-origin
fonctionne parfaitement avec des valeurs X et Y en 2D. Mais comment faire pour changer le point d’origine de transformations 3D ?
Vous l’avez peut-être deviné 😎 : on ajoute une troisième valeur à la liste ! On peut utiliser les valeurs X et Y comme en 2D, avec des pourcentages ou des mots-clés, mais l’axe Z DOIT obligatoirement être défini avec des unités réelles comme les pixels, les centimètres, etc.
.btn {
perspective: 500px;
&:active {
& > .btn__flip {
transform: rotateX(-90deg);
}
}
&__flip {
transform-style: preserve-3d;
transform-origin: center bottom 7.5vw;
transition: transform 500ms cubic-bezier(.7, 0, .23, 1);
&--off {
transform: rotateX(0deg) translateZ(7.5vw);
}
&--on {
transform: rotateX(90deg) translateZ(7.5vw);
}
}
}
Alors, tentons de combiner les fonctions de transformation 3D avec des valeurs transform-origin 3D pour créer des objets à trois dimensions, comme des boutons à plusieurs faces !
Vous trouverez le code source de notre bouton sur ce CodePen.
Avez-vous essayer de changer la vitesse de l'animation ou la couleur des faces du bouton ?
Et chose promise, chose due. Je vous parlais dans la vidéo d'introduction d'un fameux sabre Jedi : voici ce que donne une animation CSS de sabre Jedi avec la propriété transform-origin
. Le code source est ici.
Encore une fois, n'hésitez pas à manipuler les valeurs indiquées.
En résumé
transform-origin
permet de repositionner le point d’ancrage, qui se trouve par défaut au centre de l’élément ;on peut régler ce point d’origine en utilisant des unités comme px, rem, vh, etc. ;
il est aussi possible d'utiliser des pourcentages pour X et Y ;
ou encore, on peut utiliser des mots clés :
left
etright
pour l’axe X,top
etbottom
pour l’axe Y, etcenter
pour les deux ;il est possible de ne pas indiquer la valeur de l'axe Y ou, quand on utilise des mots clés, de mettre uniquement une valeur : le navigateur comprend de lui-même à quel axe la valeur s'applique ;
quand on change le point d’origine en 3D, la valeur de Z doit être exprimée en unités (et non en pourcentages) !
Créer des animations, c'est bien, mais pouvoir analyser leurs performances, c'est mieux. C'est ce que vous allez découvrir dans le chapitre suivant.