Cours CSS / transformations et transitions

Les transformations déplacent, font tourner ou mettent à l'échelle l'apparence rendue d'une boîte sans recalculer la disposition du contenu environnant. Les transitions animent un changement entre les valeurs des propriétés, il faut donc choisir les propriétés et le timing de manière délibérée et fournir une alternative pour la réduction des mouvements.

Comprendre les transformations et le flux normal

Le flux de document fait référence à la relation entre l'endroit où un élément est initialement placé et les éléments environnants. Même si vous déplacez le bouton vers le haut jusqu'à translateY(-.5rem), le paragraphe en dessous ne remonte pas en fonction de l'espace où le bouton a été déplacé. Les éléments transformés peuvent chevaucher le contenu environnant ou sortir de l'écran, donc laisser suffisamment d'espace à leur emplacement d'origine est une priorité plutôt que d'augmenter la distance de déplacement.

fonction Exemple Résultats à observer
translate() translate(1rem, -.5rem) Déplacer de 1rem vers la droite, de 0,5rem vers le haut
rotate() rotate(15deg) Faire pivoter autour d'un point de référence
scale() scale(1.05) Affiché à 1,05 fois la taille d'origine

Le fait que la taille semble plus grande ne signifie pas que l'espace occupé par la boîte avant transformation sera plus grand. Vérifiez les règles Grid ou la propriété width pour modifier la largeur réelle de la colonne de la carte, ou utilisez transform pour créer un effet visuel légèrement plus grand lors de l'appui. Les boîtes en ligne qui ne sont pas remplacées, comme le texte simple span, ne sont pas transformables, donc spécifiez display: inline-block si nécessaire. Les définitions des cibles de transformation et le traitement des coordonnées peuvent être trouvés dans le document de transformation MDN .

Comparez l'ordre de transformation et l'origine

Lorsque vous énumérez des fonctions de transformation, chaque fonction affecte le système de coordonnées utilisé par la fonction suivante. Par conséquent, translation/rotation et rotation/translation ne donnent généralement pas le même résultat. Dans l'exemple ci-dessous, la boîte tournée de A est visible à l'endroit où elle a été déplacée vers la droite, et la boîte de B a bougé dans la direction affectée par la rotation et est visible plus bas. Ne vous contentez pas de regarder le nom de la fonction et de supposer que les deux résultats sont identiques ; comparez leurs emplacements réels.

Le centre de rotation et d'expansion est défini sur transform-origin. Si vous utilisez left top au lieu du centre par défaut, il pivotera autour du coin supérieur gauche. Cela est utile lorsque vous souhaitez fixer un point spécifique, par exemple lorsqu’un menu s'ouvre, mais le chevauchement avec le contenu environnant peut changer simplement en changeant le point de référence.

Enregistrez le code suivant sous transform-compare.html en UTF-8 et ouvrez-le dans votre navigateur. Aucun fichier ou bibliothèque externe n'est requis.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Transform order and origin</title>
  <style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
.comparisons { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); gap: 1rem; }
.slot { padding: 1rem; border: 1px solid #8a9ba7; }
.frame { height: 9rem; display: grid; place-items: center; background: #f0f2f4; }
.box { width: 4rem; height: 2rem; display: grid; place-items: center; background: #166b92; color: white; }
.first { transform: translateX(2rem) rotate(45deg); }
.second { transform: rotate(45deg) translateX(2rem); }
.center { transform: rotate(30deg); transform-origin: center; }
.corner { transform: rotate(30deg); transform-origin: left top; }
  </style>
</head>
<body>
<main>
<h1>The same value also varies depending on the order and reference point</h1>
<div class="comparisons">
  <section class="slot"><h2>Translate, then rotate</h2><div class="frame"><div class="box first">A</div></div></section>
  <section class="slot"><h2>Rotate, then translate</h2><div class="frame"><div class="box second">B</div></div></section>
  <section class="slot"><h2>Center origin</h2><div class="frame"><div class="box center">C</div></div></section>
  <section class="slot"><h2>Top-left origin</h2><div class="frame"><div class="box corner">D</div></div></section>
</div>
</main>
</body>
</html>
  1. Comparez les positions de A et B. Si vous changez l'ordre des fonctions de .second pour qu'il soit le même que celui de A, les positions relatives des deux boîtes seront les mêmes. Après confirmation, remettez-le dans l'ordre initial.
  2. C et D ont le même angle de rotation. Changez uniquement transform-origin de .corner à center, vérifiez la différence dans les points de référence, puis restaurez-le à left top.
  3. Comparez le grossissement en ne changeant que la rotation de C vers scale(1.2). La zone à l'extérieur de la boîte s'agrandira, mais la zone environnante ne sera pas repositionnée. Après confirmation, restaurez-la à rotate(30deg).

Choisir les propriétés, la durée et la progression

transition ne change pas d'état par lui-même. Le changement commence uniquement lorsque la valeur CSS change au survol, à la focus ou au changement de classe. Spécifie le nom de la propriété à affecter, la durée, la courbe de progression et le délai de démarrage ; si le délai est omis, il est par défaut de 0 seconde.

transition: transform 180ms ease 0ms, background-color 180ms ease 0ms;

Ici, 180ms est de 0,18 seconde, et ease est une courbe qui relie en douceur le début et la fin plutôt que de progresser uniquement à la même vitesse. linear change à un rythme constant. Utilisez d'abord de courts temps sans délais, puis ajustez au besoin. Ajouter un long délai à un bouton apparemment inactif peut rendre difficile de remarquer les résultats de vos actions.

Mettre transition sur la règle de base lui permet de fonctionner à la fois à l'entrée et au retour. Une transition déclarée uniquement sur :hover disparaît lorsque le survol se termine et peut produire un retour différent. Nommez les propriétés délibérément au lieu d'utiliser all. Cet exemple fait transiter transform et background-color ; toutes les propriétés ne s'interpolent pas de la même façon. Pour plus de détails, consultez le document de transition MDN.

Tester le survol et la focus au clavier

Enregistrez le code ci-dessous sous transition-state.html. Lorsque vous survolez le bouton ou utilisez la touche Tab, le bouton monte et la couleur de son arrière-plan change. L’élément qui reçoit le focus est signalé par un contour bleu foncé. Le bouton est uniquement à des fins d'entraînement pour observer les changements d'état, et aucune action supplémentaire n'est effectuée après avoir appuyé sur le bouton.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Transforms and state transitions exercise</title>
  <style>
*, *::before, *::after { box-sizing: border-box; }
body { margin: 0; padding: 1rem; color: #183044; font-family: sans-serif; line-height: 1.6; }
main { max-width: 46rem; margin-inline: auto; }
h1 { font-size: 1.5rem; } h2 { font-size: 1.2rem; }
button, input { font: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 3px solid #164f73; outline-offset: 3px; }
.stage { padding: 2rem 1rem; border: 2px dashed #8a9ba7; }
.action { padding: .75rem 1.25rem; border: 1px solid #166b92; border-radius: .4rem;
  color: #183044; background: #eaf4fa; transform: translateY(0);
  transition: transform 180ms ease, background-color 180ms ease; }
.action:hover, .action:focus-visible { transform: translateY(-.5rem); background: #cfe8f4; }
.neighbor { margin-block: 1rem 0; padding: .75rem; background: #f0f2f4; }
@media (prefers-reduced-motion: reduce) {
  .action { transition: none; }
  .action:hover, .action:focus-visible { transform: none; }
}
  </style>
</head>
<body>
<main>
<h1>The paragraph stays in place as the button moves</h1>
<p>Hover over the button or press Tab to focus it.</p>
<div class="stage">
  <button class="action" type="button">Check state</button>
  <p class="neighbor">This paragraph stays in place when the button is transformed.</p>
</div>
</main>
</body>
</html>
  1. Souvenez-vous de la position supérieure du paragraphe ci-dessous et survolez le bouton. Seuls les boutons bougent et les paragraphes doivent rester à la même place.
  2. Changez la durée à deux endroits de 180ms à 800ms pour observer l'entrée et le retour, puis revenez à la valeur d'origine.
  3. Laissez le temps tel quel et changez uniquement la courbe de progression en linear pour comparaison. Ensuite, restaurez-la en ease.
  4. Ajoutez uniquement un délai 400ms à la fin de la première transition. La couleur de fond et le point de départ du mouvement changent. Supprimez ce délai après la comparaison.
  5. Placez le focus sur le bouton avec Tab, puis quittez-le avec Maj+Tab. Assurez-vous que le contour de focus et la couleur de fond décrivent l'état de fonctionnement.

Réduire le mouvement et vérifier les effets secondaires

Dans cet exemple, les règles associées à prefers-reduced-motion: reduce suppriment le déplacement décoratif tout en conservant la couleur de fond et le contour de focus. Supprimer seulement transition rendrait le changement instantané, sans retirer la position transformée. C’est pourquoi les transformations au survol et au focus passent aussi à none. La préférence n’impose pas seule ces changements : vos règles CSS définissent l’alternative. Consultez le guide MDN sur prefers-reduced-motion.

Comparez les deux états en modifiant les paramètres de votre système d'exploitation ou en reproduisant les caractéristiques multimédias dans le panneau de rendu des outils de développement de votre navigateur. Dans le réglage réduit, le bouton ne doit pas bouger, seule la couleur et l'indicateur de focus doivent changer. Une fois le laboratoire terminé, restaurez l'émulation à son état par défaut.

Un transform non-none crée un contexte d'empilement et peut établir le bloc contenant pour les descendants absolus et fixes. Si une fenêtre contextuelle ou un élément fixe se comporte de manière inattendue, inspectez les ancêtres transformés. Vérifiez également le chevauchement, le focus clavier et le mouvement réduit ; une transition fluide seule n'établit pas une mise en page utilisable. Voir CSS position : relative, absolute, fixed, et sticky, z-index et contextes d’empilement en CSS.