Les transformations 3D en CSS3

Les transformations 3D en CSS3

L’une des innovations majeures apportées par le CSS3 est la capacité à “transformer” des éléments. Ces transformations, qui peuvent être effectuées en 2D (sur la plan de la page) ou en 3D, permettent d’enrichir l’expérience utilisateur avec de tout nouveaux types d’effets visuels. Les transformations combinées avec les transitions permettent en effet d’animer des éléments HTML en effectuant des rotations, des transitions ou des changements d’échelle. Nous allons aujourd’hui appliquer ces transformations dans l’espace grâce aux transformations 3D du CSS3 !

Vincent De OlivieraCe tutoriel a été rédigé par Vincent De Oliveira, enseignant et développeur à l’ENSG. Passionné du web, il est le créateur du site CSS3create, dédié à l’expérimentation et à l’apprentissage de CSS3 ainsi que de l’outil PrefixMyCSS, permettant l’ajout automatique des préfixes propriétaires CSS. Pour suivre l’actualité de Vincent sur Twitter : @iamvdo.

Introduction

Vous avez déjà entendu parler des transformations en CSS, qu’elles soient 2D ou 3D? Vous avez déjà vu des démos, et vous aimeriez tester par vous-même? Cette approche est faite pour vous. C’est ici que ça se passe…

Quelles différences entre la 2D et la 3D sur le web?

Pour l’affichage d’un site web à l’écran, nous travaillons en 2D:

  • axe X : positif vers la droite de l’écran,
  • axe Y : positif vers le bas de l’écran.

Avec l’introduction des transformations 3D par le W3C, cela induit une nouvelle dimension:

  • axe Z : positif vers l’internaute (et donc négatif vers l’intérieur de l’écran).

Quels navigateurs sont compatibles?

À l’heure actuelle (novembre 2011), selon caniuse.com, les transformations 3D sont compatibles avec Safari 4+, Chrome 12+, IE 10+, Firefox Nightly build 10+ et sous iOS 3.2+, Android 3+.

Note: L’ajout des préfixes propriétaires reste obligatoire dans tous les navigateurs et ce, pour toutes les propriétés liées aux transformations (-webkit-, -ms- et -moz-).

Comment utiliser les transformations 3D?

Les transformations 2D ou 3D s’utilisent de la même manière. À savoir, grâce à la propriété CSS transform. C’est ensuite à l’aide des fonctions de transformations suivantes que vous pourrez utiliser la 3D:

Les rotations

  • rotate3d(x,y,z,angle) : spécifie une rotation 3D autour de l’axe défini par le vecteur (x,y,z).
  • rotateX(angle) : spécifie une rotation autour de l’axe X.
  • rotateY(angle) : spécifie une rotation autour de l’axe Y.
  • rotateZ(angle) : spécifie une rotation autour de l’axe Z. Équivalent à rotate(angle) en 2D.

Les translations

  • translate3d(x,y,z) : spécifie une translation en 3D.
  • translateZ(z) : spécifie une translation sur l’axe Z.

Les changements d’échelle

  • scale3d(x,y,z) : spécifie un changement d’échelle en 3D.
  • scaleZ(z) : spécifie un changement d’échelle sur l’axe Z.

Matrice

  • matrix3d(une matrice 4x4) : spécifie une matrice de transformation.

Note: Par défaut, toutes les fonctions de transformations sont converties en utilisant une matrice, mais cela est transparent pour nous.

Perspective

  • perspective(nombre) : spécifie la profondeur de perspective.

Il est possible d’appliquer plusieurs transformations différentes sur un même élément HTML. Pour cela, séparez les différentes fonctions par un espace. Attention toutefois, les fonctions sont appliquées dans l’ordre d’écriture, et donc l’effet final peut varier (par exemple, une rotationX de 45deg + une rotationY de 45deg n’est pas équivalente à une rotationY de 45deg + une rotationX de 45deg).

Note: Par défaut, les transformations sont appliquées par rapport au centre de l’élément. Pour modifier cela, utilisez la règle transform-origin, puis séparez les valeurs X, Y et Z par des espaces, comme ceci: transform-origin: 100px 50px 0;

Comprendre la perspective

La perspective joue un rôle primordial dans le rendu visuel des éléments en 3D. En effet, grâce à elle, vous aurez l’impression que vos éléments “sortent” de l’écran. La perspective représente la distance entre la caméra et l’élément HTML sur lequel cette perspective est appliquée:

  • Plus la perspective est importante, plus vous êtes éloignés, et donc, plus l’objet paraît plat.
  • À l’inverse, plus la perspective est faible, et plus l’élément paraît en relief.

Voici 3 schémas pour vous aider à comprendre (la perspective est représentée en vert):

Schéma n°1

  • Une perspective de 500px a été spécifiée sur l’élément conteneur.
  • L’élément conteneur (parent) et l’élément transformé (enfant) ont la même taille.

Le résultat de la transformation ressemble à un trapèze, qui nous simule l’effet de 3D.
Transformation 3D CSS3 et perspective

Schéma n°2

  • Seule la perspective a été diminuée à 400px.

Transformation 3D CSS3 - perspective 2

Le rendu de l’élément est encore un trapèze, mais l’effet 3D a été accentué.
Note: une augmentation de la perspective produirait l’effet inverse: à savoir, une réduction de l’effet 3D.

Schéma n°3

  • Une perspective de 500px a été spécifiée sur l’élément conteneur.

Par contre, l’élément transformé est, cette fois, plus petit que son conteneur, et ne se trouve pas au centre. L’effet produit est une inclinaison de l’élément, qui penche légèrement vers l’axe de la perspective.
Note: il est possible de modifier l’axe de la perspective, avec la règle CSS: perspective-origin. Elle prend deux valeurs, X et Y. Par défaut, l’origine est fixée au centre de l’élément (50% 50%).

Transformation 3D CSS3 - perspective 3

Conseil: spécifiez la perspective une fois pour toute sur l’élément conteneur qui contiendra tous les éléments à transformer, et fixez la taille de cet élément. C’est le principe d’une scène 3D.

Il est également possible de spécifier la perspective pour un seul élément avec la fonction de transformation perspective, comme ceci: transform: perspective(500px) rotateX(90deg);

Place à l’exemple : le retournement de div!

Pour réaliser cette démo, je vous conseille l’excellent JSFiddle qui vous permet de tester votre code instantanément, sinon vous pouvez bien sûr utiliser votre serveur local. Pour commencer, utilisons une simple div, que nous mettrons en forme en CSS (largeur, hauteur, couleur de fond):

div{
	width:300px;
	height:300px;
	background:red;
}

Appliquons ensuite une rotation de 45 degrés suivant l’axe X, et voyons le résultat:

div{
	/* ... */
	transform: rotateX(45deg);
}

Note : Par soucis de clarté, les préfixes propriétaires (-webkit, -moz, -o, -ms) ont été omis. Si vous souhaitez assurer un support le plus large possible (même si les navigateurs n’ont pas encore implémenté ces fonctionnalités), il est conseillé – voire obligatoire – d’utiliser les préfixes propriétaires pour que cela fonctionne.

CSS3 Transform rotateX

La transformation provoque un aplatissement de la forme, ce qui est tout à fait normal. Pour obtenir une impression de 3D (de profondeur), il faut spécifier la perspective, comme vu plus haut. Mais tout d’abord, il nous faut ajouter un bloc conteneur. Pour cela, créons une div avec un identifiant scene3D, puis ajoutons la perspective et la taille en CSS (n’oubliez pas de modifier votre sélecteur div en #scene3D div):

<div id="scene3D">
	<div></div>
</div>

Et le CSS correspondant :

#scene3D{
	width:300px;
height:300px;
	perspective:500px;
}

CSS3 Transform rotateX et perspective

L’impression de 3D est maintenant bien présente. Transformons ensuite notre code pour créer un effet de retournement sur la div (flip card). Commençons par modifier l’angle de rotation au départ, en fixant la valeur à 0. Lors du hover, cette valeur sera modifiée à 180deg.

#scene3D div{
	/* ... */
	transform: rotateX(0deg);
}
#scene3D div:hover{
	/* ... */
	transform: rotateX(180deg);
}

Pour le moment, l’effet n’est pas visible car il n’y a pas d’animation entre les 2 états (rien ne ressemble plus à un carré rouge que ce même carré rouge à l’envers…). Écrivons alors un texte dans notre div pour voir que la transformation fonctionne: lors du survol, le texte se retrouve en bas.

<div id="scene3D">
	<div>Le texte dans mon carré rouge</div>
</div>

Transform CSS3 rotate Texte

Perfectionnons ensuite notre démo en gérant une animation entre les deux angles saisis, grâce aux transitions CSS:

#scene3D div{
	/* ... */
	transform: rotateX(0deg);
	transition:all 1s ease;
}

Ainsi, l’effet visuel de retournement est visible.

Rotation 3D CSS3 flip card

Finalisons notre démo

Ce que nous voulons réaliser est simple: lors du retournement, nous voulons voir une autre div, qui s’affiche dans le bon sens. Pour cela, ajoutons d’abord une deuxième div identique à la première, puis ajoutons un nouveau conteneur qui encadre ces 2 divs:

<div id="scene3D">
	<div id="flip">
		<div>Le texte dans mon carré rouge</div>
		<div>Le texte dans mon carré vert</div>
	</div>
</div>

Modifions maintenant notre CSS pour qu’il s’adapte à la nouvelle structure. Notre transformation s’applique désormais sur l’élément id="flip", et les 2 divs sont positionnées en absolute pour créer la superposition.

#scene3D{
width:300px;
    	height:300px;
    	perspective:500px;   
}
#flip{
    	width:300px;
    	height:300px;
    	transform: rotateX(0deg);
    	transition:all 1s ease;
}
#scene3D:hover #flip{
    	transform: rotateX(180deg);
}
#flip div{
    	position:absolute;
    	width:300px;
    	height:300px;
    	background:red;       
}
#flip div:last-child{
    	background:green;
}

CSS3 3D Transformation

Note: Nous appliquons le hover sur l’élément scene3D pour éviter que ce survol ne soit interrompu pendant l’animation.
Appliquons à présent une rotationX de 180 degrés sur la deuxième div, pour qu’elle soit à l’envers. Du coup, lors du retournement de son parent, elle se retrouvera à l’endroit!

#flip div:last-child{
    	/* ... */
	transform: rotateX(180deg);	
}

Pour l’instant, un effet de scintillement se produit lors du retournement. Cela est du au fait que les deux div sont exactement superpsosées, les faces et dos de chaque élément sont confondus. Pour modifier cet affichage, ajoutons simplement la règle CSS backface-visibility:hidden sur nos divs. Ainsi, les faces arrières de ces éléments seront masquées.

#flip div{
    	/* ... */
	backface-visibility: hidden;      
}

CSS3 3D Transformation 2

Nous retrouvons donc notre carré rouge de face, et après le retournement, nous retrouvons notre carré vert de face également: les dos ont disparus!

Comment ça, c’est moche?

Pour l’instant, notre démo n’est pas attrayante, vous en conviendrez. Modifions alors notre code pour afficher une image et un texte en lieu et place de nos carrés de couleurs:

<div id="scene3D">
	<div id=”flip”>
		<div><img src="http://lorempixum.com/300/300/abstract" alt="image abstraite"/></div>
		<div><p>What a beautiful graphic!</p></div>
	</div>
</div>

Note: le site LoremPixum vous permet d’utiliser des images libres de droit facilement.

Et ajoutez un peu de CSS:

#flip div:last-child{
    	background:#333;
    	transform: rotateX(180deg);
}
#flip div:last-child p{
color:white;
    	text-shadow:0 0 1px #111;
    	font-style:italic;
padding-top:50px;
    	text-align:center;	
}

Et voilà le résultat final!

Transformation CSS3 transform final

Imbrication de plusieurs éléments

Pour une bonne compréhension du problème, remplaçons l’image de la première div par une balise p vide. Ajoutons une translation sur l’axe Z de 100px et un peu de mise en forme:

<div id="scene3D">
	<div id=”flip”>
		<div><p></p></div>
		<div><p>What a beautiful graphic!</p></div>
	</div>
</div>

Et le CSS correspondant :

#flip div:first-child p{
width:100px;
height:100px;
background: blue;
transform: translateZ(100px);	
}

On remarque que la transformation ne s’applique pas: le carré bleu reste “collé” au carré rouge. Cela est du à la façon dont les éléments imbriqués sont rendus dans un espace 3D. Par défaut, les éléments sont rendus à plat. Utilisons alors la règle transform-style:preserve-3d pour forcer la gestion du rendu 3D de ces éléments.

#flip{
	/* ... */
	transform-style:preserve-3d;
}

A présent, l’élément est bien en 3D par rapport au carré rouge. Et surtout, la 3D est préservée lors du retournement.

Conclusion

J’espère que ce tutoriel vous a plu et vous à permis de comprendre un peu plus le principe de fonctionnement des transformations 3D en CSS. N’hésitez pas à échanger sur ce sujet dans les commentaires, en bas de cet article. La démo est fonctionelle dans: Safari, Chrome et Firefox (Nightly) dans leur dernière version. Sur iPad, le hover est mal géré mais l’effet semble fonctionner. Sur IE10, un problème avec backface-visibility:hidden est à signaler.

Quelques ressources utiles:

Enfin, pour ajouter tous les préfixes propriétaires nécessaires automatiquement, vous pouvez utiliser PrefixMyCSS. Merci et à bientôt !

14 thoughts on “Les transformations 3D en CSS3

  1. Bonjour,

    Merci pour ce trés intéressant tuto.
    Je l’ai suivi à la lettre, voici ma production http://icmlicpro.free.fr/rotate/ j’ai rajouté les -moz- -webkit- -ms- a toutes les fonctions et au final la rotation (avec changement de div rouge et verte) ne fonctionne chez moi qu’avec Chrome mac 16.0.912.63
    Sur safari 5.1.2 le div rouge fait sa rotation compléte mais on ne voit pas le div vert.
    Sur Firefox mac 8.0.1 c’est la div verte que l’on voit et rien ne se passe au passage de la souris.

    Ya t’il moyen de faire marcher tout ça sur Firefox et safari ?

    Merci

  2. Salut,
    Pour Firefox, c’est normal puisque les transformations 3d en CSS ne sont implémentées qu’à partir de la version 10. Cette version est encore en bêta mais devrait voir le jour bientôt.
    Pour Safari, il faut ajouter un transform-style: preserve-3d; sur la div#flip. (PS: soit dit en passant, je n’ai toujours pas compris l’intérêt de cette propriété, puisque si l’on veut faire de la 3D, on veut voir la 3D non?)

    Sinon, voici le lien sur mon site où j’ai fait cette démo qui fonctionne normalement partout: Retournement de div en CSS

    Voilà, en espérant t’avoir aider!
    Vincent

  3. À propos de PrefixMyCSS : je préfère nettement la solution de Léa Verou, prefixfree.js qui se trouve ici : http://leaverou.github.com/prefixfree/
    Ça fait charger un script JS au lieu de charger 4 fois plus de css, et il y a forcément un temps de latence puisque les préfixes sont rajoutés à la volée mais je ne suis pas certain qu’on y perde au change et par contre quel confort !!! En outre comme elle fait évoluer son script au fur et à mesure que les nouvelles propriétés css3 sont implémentées dans les navigateurs le code est déjà définitif.
    Moi j’adore.

  4. Salut,
    Je vous felicite pour le tutoriel que vous avez crée, je commençais juste a apprendre Web GL pour créer un diaporama, ça tombe bien ;P.
    Encore merci @+

  5. Salut,
    J’ai un petit problème : je constate un écart entre l’image d’arrière plan et le div ou est inscrit le texte lors de l’effet de retournement. Comment régler ce problème?
    Merci

  6. Re salut,
    C’est bon j’ai trouvé, le problème venait en fait de la fonctionnalité “transform:translateZ(100px)” ; je devait juste diminuer les 100px et les ramener à par exemple 10px pour que les deux div se rapprochent.

    Thx again pour votre tuto

  7. Bonjour,
    Je découvre ce site et me plonge dans le css depuis peu! Voilà de quoi m’amuser un peu! :) et de m’arracher les cheveux aussi! :/

    Bon, alors j’ai suivi aussi ce tutoriel.
    Sur firefox (16.0.1) c’est beau! :) Super! merci :)

    Sur chrome (Version 22.0.1229.94) Ca rame, les changements d’états sont décallés de plusieurs secondes, les animations invisible dans ces circonstances… Mais ma machine est vieille, ma carte vidéo a souvent des raté…
    Je teste sur une autre machine encore plus vieille mais sous windows (la premiere est sous ubuntu), j’y ai la meme version de chrome mais j’obtiens pas les même résultats??? Là, pas de caré rouge, le bakface-visibility semble pas opérationnel. Pas d’effet de perspective non plus….
    je teste sur cette meme machine (windows) avec firefox. Euh, un peu vieux la version(3)! lol j’upgrade la version 12 (on me propose pas mieux) La démo transformations-3d-css3 fonctionne, mais j’ai le scintillement rouge vert au moment de l’animation. Parcontre j’ai d’autres test d’animation sur cette page qui fonctionne pas du tout… Firefox me repropose une mise à jour! Aller go… et Ah! :) la version 16! :) Tout semble comme sur ubuntu!

    Donc juste mon chrome qui est bizard! :/ et pas tester sur d’autre navigateur! Ah si IE7 mais là euh … lol! no comment!
    La page que je teste en ligne: http://www.crea-web-site.fr/test.php

    Pouvez vous m’aider a trouver d’où ça vient?

  8. Salut ! Un tuto très intéressant que j’ai pu suivre à la lettre avec succès, très pédagogique ! Petite question cela dit : après plusieurs tests, je n’arrive pas à appliquer des border-radius (avec les différents préfixes) en même temps que la propriété transform:rotateX (avec tous les préfixes également). Est-ce une mauvaise manipulation de ma part ou y’a-t-il comme une incompatibilité entre ces deux fonctions plus ou moins expérimentales et qui nécessitent toute deux les préfixes… ? Un grand merci en tout cas !

  9. J’ai beau suivre le tuto arriver au moment de mettre l’image + le texte mon cadre se dédouble avec l’image dans un carré et le texte dans un autre, tout pivote, mais en gros le texte ne veux pas se coller derrière l’image ! vous auriez une solution pour moi ?

    Merci d’avance !

    • edit : c’est dès que je met ça que ça me dédouble mon carré :

      #flip div:last-child p{
      color:white;
      text-shadow:0 0 1px #111;
      font-style:italic;
      padding-top:50px;
      text-align:center;
      }

    • rere edit : en fait c’est dès que j’ai une deuxième division avec le texte que j’ai un deuxième cadre quand je n’ai qu’une div avec l’image je n’ai qu’un carré

  10. Je n’arrive pas à intégrer une vidéo style youtube dans les div avec cette transformation 3D. Je suppose que c’est lié à l’axe Z. Mais si vous pouvez m’aider.
    Merci d’avance.

    • Edit :
      Pour mieux expliquer, j’ai un écran noir qui s’affiche au lieu de la vidéo.
      Problème que je n’avais que sur Firefox. Après l’avoir mis en ligne, je me suis apperçu que la vidéo était affichée. Il s’agit donc d’un soucis en local. Pourquoi ne veut t’il pas afficher la video youtube sur firefox quand je suis en local ? Pb de lien?

  11. Bonjour, merci pour ce tutoriel très bien réalisé.
    On en apprends davantage chaque jour sur le CSS3 ; il n’a pas fini de nous surprendre ! Votre article est très clair et le petit cours sur la perspective bien utile. Merci :)

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>