Découverte des transitions CSS3Flux RSS

Publié le 31/10/2011 à 16:44 dans la catégorie Programmation Web.
Tags : css3, transition, infoject', développement, web.
1 commentaire.

Introduction

Je profite de l'arrivée du nouveau site Infoject' pour faire un petit tutoriel sur les transitions en CSS. Quand je parle de transition, je parle du changement progressif sur une certaine durée d'une ou plusieurs propriétés CSS qui permettent d'adoucir un effet visuel. Il était généralement possible d'effecter cette transition en JavaScript au préalable, mais maintenant, plus besoin de la moindre ligne de code en JavaScript. Seules quelques lignes de CSS dans la feuille de style suffisent à effectuer des transitions.

Depuis leurs intégrations dans les principaux navigateurs, nous utilisons les transitions très largement dans nos productions. Les liens sont généralement les premiers éléments à en bénéficier et l'effet rendu est bien plus agréable à l'œil. Cependant, sur notre site nous avons préféré jouer sur la décoration du texte via la propriété text-decoration pour ajouter le souligner aux liens en cours de survol ou de sélection. Cette propriété n'est toutefois pas du tout adaptée au style du menu. Il fallait donc trouver un autre effet que la modification de couleur que nous avons tendance à trop utiliser et l'effet de souligner.

Menu au repos

La solution mise en place est le déplacement vertical des liens de quelques pixels lors d'un survol ou d'une sélection de l'élément. Cet effet visuel sera aussi appliqué lorsque la page que l'on consulte correspond à la page affichée en cliquant sur ce même lien. Pour conserver un effet au survol du lien dans la page consultée, nous avons ajouté un effet miroir sur la première lettre du mot présent dans la balise <strong> grâce à la propriété transform.

Menu avec lien Blog actif

Principe de fonctionnement

Le principe est plutôt simple à comprendre et à utiliser. On souhaite passer les propriétés d'un élément d'un état A à un état B avec un effet de transition plus agréable qu'une modification brusque de ses propriétés.

Pour le menu, on souhaite décaler un lien de quelques pixels vers le bas. On va donc jouer sur la taille du padding-top lors de l'évènement hover et focus sur ce lien.

Passage de l'état A à l'état B
Passage de l'état A à l'état B lors du focus.

La transition est ajoutée simplement dans les règles CSS des liens du menu, et son décalage dans les règles du sélecteur CSS :hover et :focus.

/* Règles des liens du menu */
header nav ul a{
    color:#333;
    display:inline-block;
    text-decoration:none;
    text-shadow:1px 1px #fff;
    transition:250ms;
}

header nav ul a:hover, header nav ul a:focus, header nav ul a.current{
    padding-top:7px;
    outline:none;
    text-decoration:none;
}

Plutôt que de me contenter de copier / coller le code du menu bêtement, je vous propose un récapitulatif des spécifications du W3C sur les transitions avec quelques exemples. Pour ceux que ça n'interesse pas, vous pouvez accéder directement à l'exemple du menu.

Propriétés & Syntaxes d'écriture

Pour faire fonctionner une transition, il est possible de définir 4 paramètres, dont un obligatoire, via les propriétés CSS suivantes:

  • transition-property: Le nom de la propriétés sur laquelle s'applique la transition. Par défaut all.
  • transition-duration: La durée de la transition pour passer de l'état d'origine, à l'état défini dans l'évènement. Par défaut 0 (donc pas de transition).
  • transition-timing-function: La fonction utilisée pour la transition. Par défaut ease.
  • transition-delay: Le délai avant le lancement de la transition après son déclenchement. Par défaut 0.

transition-property

Les transitions CSS ne peuvent s'appliquer que sur certaines propriétés. Par défaut, si une durée de transition est indiquée à un élément, les transition s'effectueront sur toutes les propriétés compatibles (valeur all). Si vous ne souhaitez pas que toutes les propriétés soient affectées, il faut préciser ici le nom des propriétés.

/* Exemple transition-property */
div{
    transition-property:color, text-shadow;
}

Vous pouvez consulter la liste des propriétés compatibles ici.

Note

Si vous souhaitez appliquer une transition à une propriété qui nécessite un préfixe, ajoutez simplement le préfixe à la propriété.

transition-property:-moz-border-radius;

transition-duration et transition-delay

Vous pouvez définir le temps que va mettre la transition à s'effectuer et le délai d'attente entre le moment ou l'évènement est déclenché (un :hover sur un élément par exemple) et le début de la transition. Il faut indiquer des valeurs de type "time", en secondes ou millisecondes de la manière suivante:

/*
* Exemple transition-duration et transition-delay
* La transition durera 0,3 secondes
* et commencera 0,2 secondes après l'évènement déclencheur
*/

div{
    transition-duration:.3s;
    transition-delay:200ms;
}

transition-timing-function

Il est possible d'indiquer la fonction de transition à utiliser. L'intérêt est assez simple à comprendre. Prenons un cas ou l'on souhaite déplacer un élément de 120 pixels vers la droite. Plutôt que de décaler obligatoirement ce bloc de manière linéaire, il est possible d'adoucir son déplacement avec une fonction. La valeur ease permettra par exemple de voir le cube accélérer progressivement, puis ralentir à la fin de la transition.

Quelques fonctions sont définies par défaut, mais il est possible de définir sa propre fonction simplement. Bien souvent, la valeur ease qui est définie par défaut vous conviendra, mais tout dépend de l'utilisation faite de vos transitions. Les fonctions prédéfinies sont les suivantes:

  • ease: Valeur par défaut, effet d'accélération et de décélération. Équivaut à cubic-bezier(0.25, 0.1, 0.25, 1).
  • linear: Fonction linéaire, aucun effet d'accélération ou de décélération. Équivaut à cubic-bezier(0, 0, 1, 1).
  • ease-in: Effet d'accélération mais pas de décélération. Équivaut à cubic-bezier(0.42, 0, 1, 1).
  • ease-out: Pas d'effet d'accélération mais effet de décélération. Équivaut à cubic-bezier(0, 0, 0.58, 1).
  • ease-in-out: Effet d'accélération et de décélération très rapides. Équivaut à cubic-bezier(0.42, 0, 0.58, 1).
  • cubic-bezier(x1, y1, x2, y2): Permet de définir sa propre fonction en indiquant les coordonnées des points de contrôle P1 et P2 entre 0 et 1.

Le schéma suivant permet de bien comprendre le fonctionnement de ces fonctions par rapport aux points de repères P1 et P2:

Les points de contrôle de la fonction de transition
Schéma du W3C indiquant les points de contrôle pour la fonction de transition.

Utilisation des préfixes

Les transitions CSS étant toujours en chantier du coté du W3C, il faut pour le moment utiliser les préfixes liées aux moteurs de rendus des navigateurs avant chaque déclaration de propriété. Pour rendre son code compatible avec les 5 principaux navigateurs du marché (ceux pour lesquels nous testons le rendu de nos production), il faut donc écrire 6 lignes pour une même propriété:

/* Exemple de déclaration de la propriété transition-delay */
.current .reverse{
    -webkit-transition-delay:0s;
    -moz-transition-delay:0s;
    -ms-transition-delay:0s;
    -o-transition-delay:0s;
    transition-delay:0s;
}

Mais comme il en va de même pour la plupart des propriétés CSS3, vous devez commencer à avoir l'habitude. Pour éviter de dupliquer trop de code, j'évite les préfixes dans les exemples, mais n'oubliez pas de les rajouter pour rendre votre code fonctionnel.

Une ligne pour les contrôler tous

Il est possible d'utiliser la propriété transition: qui permet de déclarer l'ensemble des propriétés en une ligne. La syntaxe est la suivante :

transition: <property> || <duration> || <timing-function> || <delay> /*
* Transition sur toutes les propriétés CSS de l'élément
* en 0,3 secondes avec la fonction ease sans délai
* Ces cinq déclarations sont équivalentes
*/

transition:.3s;
transition:all 300ms;
transition:ease 300ms 0;
transition:all ease 300ms;
transition:all cubic-bezier(0.25, 0.1, 0.25, 1.0) 0.3s 0s;

Il est possible de déclarer plusieurs transitions sur un même élément en séparant les déclarations par des virgules.

/*
* Transition sur la couleur du texte en 0,3 secondes avec la fonction ease sans délai
* et sur l'ombre du texte en 0,4 secondes avec la fonction linear après 0,3 secondes
*/

transition:color .3s, text-shadow .4s linear .3s;

Cette unique ligne revient à écrire :

/*
* Transition sur la couleur du texte en 0,3 secondes avec la fonction ease sans délai
* et sur l'ombre du texte en 0,4 secondes avec la fonction linear après 0,3 secondes
*/

transition-property:color, text-shadow;
transition-duration:.3s, .4s;
transition-timing-function:ease, linear;
transition-delay:0, .4s;

Propriétés CSS compatibles

En raison de la nature variée des effets existants en CSS, les transitions ne peuvent s'appliquer que sur certaines propriétés et, dans certains cas, pour certains types de valeur uniquement. Le W3C indique dans les spécification des transitions que les propriétés CSS suivantes doivent être compatibles :

  • background-color
  • background-image
  • background-position
  • border-color
  • border-radius
  • border-spacing
  • border-width
  • bottom
  • box-shadow
  • color
  • crop
  • font-size
  • font-weight
  • grid-collums
  • grid-rows
  • height
  • left
  • letter-spacing
  • line-height
  • margin
  • max-height
  • max-width
  • min-height
  • min-width
  • opacity
  • outline-color
  • outline-offset
  • outline-width
  • padding
  • right
  • text-indent
  • text-shadow
  • top
  • vertical-align
  • visibility
  • width
  • word-spacing
  • z-index
  • zoom

Bien que non présentes dans cette liste, certaines fonctions de la propriété transform sont également compatibles, dont la fonction scaleX(), que nous utilisons pour faire un effet miroir.

D'autres propriétés sont supportées en fonction des navigateurs. Je pense qu'on peut compter sur le support à plus ou moins long terme de toutes les propriétés CSS définies par des valeurs numériques (dimensions, espacements, durées, fonctions, couleurs...).

Note

Toutes ces propriétés ne sont pas encore supportées par tous les navigateurs (les dégradés par exemples).

Et en JavaScript ?

Définition et modification des règles de transition

Il est possible de modifier les propriétés de transition d'un élément en JavaScript en modifiant ses propriétés de style :

var div = document.getElementById("div_exemple");

// Déclaration compacte de la règle de transition
div.style.transition = "color .3s, text-shadow .4s linear .3s;";

// Déclaration détaillée
div.style.transitionProperty = "color, text-shadow;";
div.style.transitionDuration = ".3s, .4s;";
div.style.transitionTimingFunction = "ease, linear;";
div.style.transitionProperty = "0, .3s;";

Modification des règles CSS de l'élément

Si vous modifiez une propriétés de style CSS d'un élément à partir d'un code JavaScript, et qu'une règle de transition est appliquée sur la propriété de cet élément, la règle de transition s'appliquera. Il en va de même si vous modifiez la classe de l'élément.

Évènement JavaScript

Un évènement JavaScript est déclenché lorsqu'une transition se termine. Il est ainsi possible d'effectuer une action à la suite de cet évènement.

// Écoute de l'évènement appelé à la fin de la transition
document.getElementById("mondiv").addEventListener("transitionend", maFonction, true);
Note

Le nom de l'évènement varie en fonction des navigateurs :

  • transitionend pour Firefox
  • webkitTransitionEnd pour Chrome et Safari
  • oTransitionEnd pour Opera

Menu Infoject' : Le code de base

Comme nous souhaitions nous faire la main sur la nouvelle norme HTML5, notre site est développé avec ce doctype. Mais pas de panique si vous souhaitez adapter ce tutoriel pour un doctype différent, le code HTML n'a que peu d'importance dans notre exemple.

Les propriétés de transition CSS ne sont pas présentes et seront rajoutées dans la partie suivante pour faciliter la compréhension du code. Les effet présent au survol des liens (décalage vertical et effet miroir) sont toutefois présents.

Les liens du menu sont placés dans une liste non ordonnée <ul> qui est placée dans une balise <nav> du <header>. Un <strong> est ajouté aux liens et la première lettre du <strong> est placée dans un <span> auquel on ajoute la classe reverse. La classe current est ajoutée au lien de la page affichée actuellement.

<a href="#" class="current">
    Le<br/><strong><span class="reverse">B</span>log</strong>
</a>

La transition verticale

Dans le cas de notre transition vertical, je vais donc modifier la propriété padding-top des liens lors du survol pour ajouter 7 pixels. Les liens devront donc être en display:inline-block pour que le padding soir interprété. Il est préférable de modifier le padding de l'élément plutôt que le margin pour que l'utilisateur puisse toujours cliquer sur le lien malgré son déplacement.

On ajoute les propriétés de transition aux liens du menu :

/* Style des liens du menu supérieur avec les transitions */
header nav ul a{
    color:#333;
    display:inline-block;
    text-decoration:none;
    text-shadow:1px 1px #fff;

    -moz-transition:250ms;
    -webkit-transition:250ms;
    -o-transition:250ms;
    -ms-transition:250ms;
    transition:250ms;
}

Bien que les transitions s'appliqueront sur toutes les propriétés CSS des liens au survol puisque aucune propriété n'a été indiquée dans les déclarations, seul le déplacement vertical se verra car le padding est la seule propriété modifiée dans la déclaration lors du :hover et sur :focus des liens.

Rotation de la première lettre

On ajoute maintenant les propriétés de transition à la classe .reverse permettant d'effectuer la transition sur l'effet miroir. Notez le délai de 0,3 seconde qui permet de débuter la rotation de la première lettre uniquement après la fin de la transition verticale.

Comme il n'y a pas de transition pour le lien de la page affichée, on modifie le délai des transitions pour que l'effet miroir soit lancé immédiatement au survol.

/* Transition sur l'effet miroir de la première lettre */
.reverse{
    -moz-transition:-moz-transform 250ms ease .3s;
    -webkit-transition:-webkit-transform 250ms ease .3s;
    -o-transition:-o-transform 250ms ease .3s;
    -ms-transition:-ms-transform 250ms ease .3s;
    transition:transform 250ms ease .3s;
}

/* Modification du délai avant le lancement de la transition pour le lien de la page affichée */
.current .reverse{
    -moz-transition-delay:0s;
    -webkit-transition-delay:0s;
    -o-transition-delay:0s;
    -ms-transition-delay:0s;
    transition-delay:0s;
}
Note

J'aurais bien aimé pouvoir utiliser le sélecteur CSS :first-letter appliqué aux éléments <strong> du menu, mais celui-ci permet de ne gérer officiellement que certaines propriétés et transform n'en fait malheureusement pas partie. L'ajout d'un <span> avec une classe particulière autour de la première lettre est donc la seule solution possible.

Résultat

Support actuel

Les transitions CSS3 sont supportées par les principaux navigateurs, sauf Internet Explorer pour lequel il faudra attendre la version 10. L'utilisation des préfixes devant les déclarations est obligatoire pour tous ces navigateurs à l'heure actuelle.

Firefox Chrome Opera Safari Internet Explorer
Avec le préfixe -moz- Avec le préfixe -webkit- Avec le préfixe -o- Avec le préfixe -webkit- Version 10 avec le préfixe -ms-
Ressources utiles