Édition Nº17 du 4 septembre 2012 Retour au sommaire

Les transitions et animations CSS

Les transitions et les animations CSS vous semblent être une nouvelle destination passionnante mais quelques peu aventureuse pour vous y rendre seul ? Accompagnez Vincent De Oliveira qui va débroussailler pour vous ce pan des feuilles de styles, et vous permettre d’avancer par la suite en meilleure autonomie.

Conducteur


Vincent De Oliveira

Arrêts prévus :

Introduction

Depuis toujours, les concepteurs web ont tenté de styler et de dynamiser des pages HTML terriblement monotones. À la fin des années 90, un simple effet de survol ne peut pas être réalisé facilement : l’utilisation de JavaScript est inévitable, mais impose de connaître la programmation. L’arrivée des pseudo-classes dynamiques au sein de CSS (:hover, :focus, :active…) a alors facilité l’opération et permis de s’affranchir de scripts souvent lourds.

Plus tard, lorsque que la mode était aux ombres portées et aux coins arrondis, les techniques passaient par la surcharge du balisage HTML et la création d’images étirables, ce qui nuisait considérablement à la sémantique et à l’accessibilité (si toutes les précautions n’étaient pas prises). Aujourd’hui, avec CSS3 et les propriétés box-shadow et border-radius, ces effets sont facilement réalisables et les anciennes techniques sont fortement déconseillées.

Parallèlement, de nombreux designers-développeurs, frustrés des possibilités offertes par les standards web, se tournèrent vers des solutions radicales, comme Flash, notamment pour ses capacités d’animation, de transformation d’objets dans l’espace, de gestion des textes et du multimédia. Malheureusement, Flash pose de gros soucis d’accessibilité qui sont accentués aujourd’hui sur plateforme mobile où la plupart des appareils ne le supportent pas.

C’est pourquoi le langage CSS se devait d’offrir des fonctionnalités équivalentes pour l’enrichissement de l’expérience utilisateur. C’est désormais chose faite en ce qui concerne les animations d’objets et les transformations géométriques, puisque trois modules dédiés sont arrivés au terme de leur étude par le W3C :

  • Transitions CSS ;
  • Animations CSS ;
  • Transformations CSS.

Cet article détaille l’utilisation et la mise en place des transitions et animations CSS dans vos projets web.

Transitions et animations en CSS, c’est quoi ?

Les transitions et animations permettent de nouvelles interactions avec l’internaute en favorisant son ressenti (et donc son impression positive) sur le produit qu’il est train d’utiliser. L’ajout subtil de ces transitions et/ou animations améliore grandement le design des interfaces et permet d’en accroître l’utilisabilité.
Mais quelle est la différence entre transitions et animations ?

Les transitions

Une transition CSS est le fait d’animer le changement de valeur d’une propriété (d’une valeur A à une valeur B), comme par exemple le changement de couleur d’un élément de color: red; à color: blue;, ou encore le changement de taille de width: 50px; à width: 100px;. Cette transition intervient lors d’un changement d’état, qui peut être :

Afin de gérer cette transition, cinq propriétés sont définies :

  • transition-property : la (les) propriété(s) à animer ;
  • transition-duration : la durée de la transition ;
  • transition-delay : le délai avant que l’animation ne se lance ;
  • transition-timing-function : la méthode d’interpolation (départ rapide, lent…) ;
  • et transition : c’est la propriété raccourcie des quatre précédentes.

Par défaut, toutes les propriétés sont animées (avec le mot-clé all), la durée est de 0 seconde et la méthode d’interpolation est ease (nous y reviendrons). Cela signifie que le code minimal pour réaliser une transition est :

1
2
3
#elem {
    transition: 1s;
}

Ce qui équivaut à :

1
2
3
4
5
#elem {
    transition-property: all;
    transition-duration: 1s;
    transition-timing-function: ease;
}

Dans ce cas, toutes les propriétés animables appliquées à #elem lors de son changement d’état subiront une transition de 1 seconde. Retrouvez la liste des propriétés animables sur le site du W3C.

Voici un exemple concret pour réaliser une transition linéaire de 1 seconde sur la largeur et la couleur d’arrière-plan d’un élément :

1
2
3
#elem {
    transition: width 1s linear, background-color 1s linear;
}

Voir la démonstration 1

Les animations

Une animation CSS correspond à plusieurs transitions qui s’enchaînent. Une animation permet par exemple un changement de couleur de color: red; à color: blue;, puis de color: blue; à color: green;. Pour cela, chaque transition est donc définie sous forme d’étape (en pourcentage de l’animation globale) via la règle @keyframes.

Création d’une animation de changement de taille :

1
2
3
4
5
@keyframes nomAnim {
    0%   { width: 50px;}
    50%  { width: 200px;}
    100% { width: 100px;}
}

Cette animation définit donc 2 changements de taille : d’abord de width: 50px; à width: 200px;, puis de width: 200px; à width: 100px;. Pour définir les étapes, il existe également deux mots-clés: from qui équivaut à la valeur 0%, et to qui équivaut à la valeur 100%. De plus, il est possible d’ajouter plusieurs étapes séparées par des virgules pour le même groupe de propriétés, comme ceci :

1
2
3
4
5
@keyframes nomAnim {
    from, to { width: 100px;}
    25%, 75% { width: 200px;}
    50%      { width: 50px;}
}

Cette animation peut ensuite être appliquée par le biais de neuf propriétés :

  • animation-name : le nom de l’animation à utiliser ;
  • animation-duration : la durée complète de l’animation ;
  • animation-delay : le délai avant que l’animation ne se lance ;
  • animation-timing-function : la méthode d’interpolation (départ rapide, lent…) entre chaque étape (voir plus bas) ;
  • animation-iteration-count : le nombre de fois où l’animation est répétée. Le mot-clé infinite permet d’effectuer l’animation en boucle ;
  • animation-direction : permet de jouer l’animation en sens inverse ;
  • animation-fill-mode : état des éléments avant et après l’exécution de l’animation (voir plus bas) ;
  • animation-play-state : permet de mettre l’animation en pause ;
  • animation : c’est la propriété raccourcie des huit précédentes.

Par défaut, la durée est de 0 seconde, le nombre de répétitions est 1 et la méthode d’interpolation est ease. Les autres propriétés sont optionnelles. Cela signifie que le code minimal pour lancer une animation définie avec @keyframes est :

1
2
3
#elem {
    animation: nomAnim 1s;
}

Exemple d’une animation sur la taille et la couleur d’arrière-plan, de manière infinie :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@keyframes anim1 {
    from {
        width: 300px;
        background: greenyellow;            
    }
    50%  {
        width: 600px;
        background: deepskyblue;    
    }
    to   {
        width: 450px;
        background: yellowgreen;            
    }
}
#elem {
    animation: anim1 3s infinite; 
}

Voir la démonstration 2

Ajouter une transition/animation

Nous l’avons vu, une transition/animation se lance lors d’un changement d’état. Mais à quel endroit appliquer les propriétés ?
Il y a trois cas de figure qui fonctionnent de la même façon pour les transitions et les animations :

Lors du changement d’état

1
2
3
4
5
6
7
ul a img {
    margin-right: 5px;
}
ul a:hover img {
    margin-right: 15px;
    transition: margin-right 0.5s;
}

Dans ce cas, la transition aura lieu lorsque la souris arrive sur l’élément, mais pas lorsqu’elle le quitte.

Voir la démonstration 3

À l’état initial

1
2
3
4
5
6
7
ul a img {
    margin-right: 5px;
    transition: margin-right 0.5s;
}
ul a:hover img {
    margin-right: 15px;        
}

Dans ce cas, la transition aura lieu lors des deux évènements : lorsque la souris arrive sur l’élément et lorsqu’elle le quitte.

Voir la démonstration 4

À l’état initial et lors du changement d’état

1
2
3
4
5
6
7
ul a img {
    margin-right: 5px;
    transition: margin-right 0.2s 1s;
}
ul a:hover img {
    transition: margin-right 0.5s;        
}

Dans ce cas, deux transitions ont lieu. Lorsque la souris arrive sur l’élément, une transition de 0.5 secondes est lancée. Lorsqu’elle le quitte, c’est une transition de 0.2 secondes mais avec un délai de 1 seconde.

Voir la démonstration 5

Contrôler les transitions/animations

Bien que les contrôles restent simples, il est toutefois possible de réaliser quelques opérations intéressantes. C’est surtout le cas pour les animations CSS qui permettent plus de finesse dans les réglages.

Modifier la méthode d’interpolation

La méthode d’interpolation spécifie la façon dont l’animation évolue dans le temps. C’est la propriété *-timing-function. Par exemple, lors d’une transition de width: 50px; à width: 100px; qui dure 2 secondes, la largeur ne sera pas forcément 75px à 1 seconde ! L’évolution de l’animation peut être définie par 5 mots-clés et 2 fonctions :

  • linear : méthode linéaire ;
  • ease : le départ est rapide, l’accélération lente. L’accélération semble naturelle ;
  • ease-in : le départ est lent. L’arrivée semble donc plus rapide ;
  • ease-out : l’arrivée est lente. Le départ semble donc plus rapide ;
  • ease-in-out : le départ et l’arrivée sont lents ;
  • cubic-bezier(p2x,p2y,p3x,p3y) : courbe d’accélération personnalisée ;
  • steps(nb, sart|end) : animation par palier (image par image). Les transitions/animations ne sont plus fluides.
Schéma des courbes de Bézier par défaut des transitions et animations CSS
Schéma des courbes de Bézier par défaut des transitions et animations CSS

Voir la démonstration 6

La fonction cubic-bezier()

La fonction cubic-bezier() permet un contrôle poussé de la courbe d’accélération (même si nous sommes encore très loin des capacités de Flash). Quatre points p1, p2, p3, p4 sont nécessaires pour définir une courbe de Bézier. Les points p1 et p4 sont respectivement le point de départ et d’arrivée. Les points p2 et p3 sont les tangentes des points p1 et p4 qui définissent la direction et la longueur de la courbe. La fonction cubic-bezier() prend quatre paramètres qui sont respectivement :

  • la valeur X du point p2 ;
  • la valeur Y du point p2 ;
  • la valeur X du point p3 ;
  • la valeur Y du point p3.

Sachant que les points p1 et p4 sont obligatoirement le point (0,0) et (1,1).

Les valeurs X doivent êtres comprises entre 0 et 1, car elles correspondent au temps qui passe. Les valeurs Y, elles, peuvent être inférieures à 0 ou supérieures à 1. Dans ce cas, des effets de rebonds peuvent êtres réalisés puisque les valeurs des propriétés seront hors bornes. Par exemple, lors d’une transition de width: 50px à width: 100px, il est possible que la valeur de width soit supérieure à 100px.

Voici un exemple utilisant deux courbes de Bézier personnalisées :

1
2
3
4
5
6
#elem {
    transition: 1s cubic-bezier( 0.5, 1, 0.5, 0.8); 
}
#elem {
    transition: 1s cubic-bezier( 0.5, 2, 0.5, 0.8);
}
Deux exemples de courbes de Bézier personnalisées pour les transitions et animations CSS
Deux exemples de courbes de Bézier personnalisées pour les transitions et animations CSS

Voir la démonstration 7

Liens utiles pour comprendre les courbes de Bézier en CSS :

La fonction steps()

La fonction steps() permet de jouer une animation en mode “image par image”. Voici un exemple de ce qu’il est possible de réaliser à l’aide de sprites (bienvenue à l’époque des GIFs animés !) :

Voir la démonstration 7a

Jouer une animation en sens inverse

Pour les animations uniquement, il est possible de prévoir que certains cycles soient joués en sens inverse. La propriété animation-direction accepte 4 valeurs :

  • normal : l’animation est jouée normalement, de l’étape 0 % (from) à l’étape 100 % (to) ;
  • reverse : l’animation est jouée en sens inverse, de l’étape 100 % à l’étape 0 % ;
  • alternate : l’animation est jouée normalement les cycles impairs (1,3…) et en sens inverse les cycles pairs (2,4,…) ;
  • alternate-reverse : l’animation est jouée en sens inverse les cycles impairs (1,3…) et normalement les cycles pairs (2,4..).

Cette propriété est très pratique pour revenir à l’état d’origine en jouant une animation en sens inverse, ou pour réaliser des effets d’apparition/disparition.

1
2
3
4
5
6
7
8
9
10
11
@keyframes pulse {
    from {
        box-shadow: 0 0 0px deepskyblue;
    }
    to {
        box-shadow: 0 0 14px deepskyblue;
    }
}
input:focus {
    animation: pulse 1s infinite alternate;
}

Voir la démonstration 8

Gérer l’état des éléments animés avant et après l’animation

Par défaut, une animation modifie les valeurs des propriétés pendant son exécution uniquement. Cela signifie qu’avant le début de l’animation, les éléments sont tels que définis dans le code CSS, et qu’à la fin de l’animation, les éléments reviennent à leur état d’origine. La propriété animation-fill-mode permet donc de conserver l’état de fin ou de début d’animation avant que celle-ci ne soit jouée. Les valeurs sont :

  • backwards : les éléments sont tels que définis à l’étape 0 % de l’animation avant le début de celle-ci ;
  • forwards : les éléments sont tels que définis à l’étape 100 % de l’animation après la fin de celle-ci ;
  • both : combinaison de backwards et forwards ;
  • none : par défaut.

Voici un exemple ou les 4 cas sont mis en situation. Un élément centré subit une animation qui modifie sa position et simule un rebond :

  • Cas 1: none : l’élément est modifié lors de l’animation et revient à son état d’origine à la fin ;
  • Cas 2: backwards : avant l’animation, l’élément est en haut (état from). À la fin, l’élément revient en position d’origine (centrée) ;
  • Cas 3: forwards : avant l’animation, l’élément est centré. À la fin, l’élément reste en bas (état to) ;
  • Cas 4: both : l’élément est en haut au départ et reste en bas à la fin.

Voir la démonstration 9

Les limitations

Bien que tout paraisse rose, certaines limitations existent. En voici quelques unes :

  • Toutes les propriétés ne sont pas animables. Par exemple, une transition/animation de display: none; à display: block; n’est pas possible. Voici la liste complète des propriétés animables ;
  • Les étapes d’une animation se définissent en pourcentage de l’animation totale. Dans le cas d’une animation précise, il est souvent nécessaire de définir des nombres décimaux à rallonge (par exemple 33.333%). Il serait parfois plus évident de définir les étapes en secondes ;
  • Les transitions/animations sont censées fonctionner sur les pseudo-éléments (::before et ::after), mais malheureusement seul Firefox les supporte ;
  • Lorsqu’un délai est fixé, il n’est valable que pour la première itération d’une animation. Pour lancer une animation avec un délai à chaque itération, il faut bien souvent ruser et créer une animation qui n’effectue aucune tâche pendant les n premiers pourcentages (ce qui n’est pas toujours simple) ;
  • Il n’existe pas de synchronisation à proprement parler. Par exemple, il n’est pas possible de lancer une animation lorsqu’une autre se termine et dont la durée n’est pas connue. Cependant, de nouveaux évènements JavaScript sont propagés (voir plus bas) ;
  • Les animations ne peuvent pas suivre un chemin ou une forme (peut-être dans le futur en utilisant le principe des formes définies dans le module des Exclusions CSS) ;
  • Et bien entendu, toutes les limitations liées au langage CSS lui même: pas de variable, pas de calcul, pas de changement de valeurs pendant le déroulement d’une transition/animation…

Les bonnes pratiques d’intégration

Je vous entends déjà dire : « C’est bien beau les transitions/animations mais en pratique ça donne quoi ? C’est trop tôt, hein ? »
Et bien non, et ce pour deux raisons :

Il est vrai qu’à l’heure actuelle (septembre 2012), les transitions/animations doivent encore êtres préfixées pour pouvoir êtres utilisées sur certains navigateurs. Mais dans très peu de temps, ce ne sera plus nécessaire. Ce n’est qu’une question de mois ! La mise en place des transitions/animations doit cependant se faire sur le principe de l’amélioration progressive (progressive enhancement), c’est à dire qu’elles doivent êtres mises en place pour améliorer l’expérience l’utilisateur, sans interférer avec les fonctionnalités du site ni rendre un élément inaccessible ou inutilisable. Le site doit être fonctionnel avant l’ajout des transitions/animations. Il n’est donc pas primordial (voire tout simplement utile) de mettre en place des solutions de repli pour les navigateurs non compatibles. Cependant, des solutions existent :

Voici un exemple complet avec préfixes (le préfixe -ms- a été volontairement ôté, puisque IE10 supporte la version non-préfixée et qu’IE9 et inférieurs ne supportent pas du tout les transitions) :

1
2
3
4
5
6
#elem {
    -webkit-transition: width 2s ease-out;
    -moz-transition: width 2s ease-out;
    -o-transition: width 2s ease-out;
    transition: width 2s ease-out;
}

Exemples d’intégration

Voici à titre d’apprentissage et d’inspiration quelques intégrations des transitions et animations :

Aller plus loin : les évènements JavaScript

Afin d’intégrer les transitions et animations dans un contexte d’application JavaScript, de nouveaux évènements peuvent êtres récupérés. Il est par exemple possible de détecter la fin d’une transition ou encore le début, la fin ou la répétition d’une animation. Les évènements sont donc respectivement: transitionend, animationstart, animationend, animationiteration.

Pour les utiliser, il faut d’abord “écouter” l’un des évènements et attacher une fonction qui sera exécutée lorsque l’évènement se produira :

1
2
3
4
var elem = document.getElementById(‘elem’);
elem.addEventListener(‘transitionend’, function(e) {
    alert(‘La transition “‘+e.propertyName+’” est finie!’);
}, false);

Voir la démonstration 10

Comme pour les propriétés, les évènements doivent encore être préfixés. Le tableau suivant précise la syntaxe pour chaque préfixe (avec pour exemple transitionend) :

Préfixe Evènement
-webkit- webkitTransitionEnd
-moz- transitionend
-ms- MSTransitionEnd
-o- oTransitionEnd

Grâce à ces évènements, il devient donc possible de synchroniser les transitions/animations, comme par exemple lancer une animation lorsqu’une autre se termine ou commence via l’ajout de l’attribut class en JavaScript. Dans le cadre d’une mise en place en production, pensez à utiliser Modernizr, une librairie JavaScript qui simplifie l’utilisation des préfixes et aide à la mise en place de l’amélioration progressive.

Conclusion

Les transitions/animations ne doivent pas êtres vues comme quelque chose de futile ou superflu. Au contraire, elles sont une valeur ajoutée incontournable dans tout design web d’aujourd’hui. Il faut cependant apprendre à les mettre en place avec parcimonie, car leur utilisation trop intensive peut vite provoquer l’effet inverse, à savoir un effet brouillon. De plus, certaines limitations liées à la performance du navigateur peuvent êtres ressenties, notamment une perte de fluidité ou des délais non respectés. Ce n’est pas parce que tout est possible qu’il faut obligatoirement tout faire…

Les transitions et animations CSS

Note de cet article : 3 / 5

Pour pouvoir noter les articles, vous devez voyager avec un billet (c'est gratuit !).
Toutes les infos sur la page d'abonnement !
Déjà inscrit ? Connectez-vous.

Vincent De Oliveira est formateur web à l'ENSG (École Nationale des Sciences Géographiques). Passionné du web, il est le créateur du site http://css3create.com, dédié à l'expérimentation et à l'apprentissage de CSS3. Il écrit occasionnellement des articles techniques pour plusieurs médias (presse écrite, web) et partage ses découvertes et conseils sur son blog http://iamvdo.me. Il dispense également quelques conférences afin de promouvoir les standards web et a co-écrit le livre "CSS3 Le design web moderne" aux éditions Dunod.

Pas (encore) de réactions (RSS)

Réagir à cet article

XHTML : Vous pouvez utiliser ces balises : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>