Sphères en CSS3

Donovan Hutchinson

Traducteur

rodolphebrd

Je vous ai récemment expliqué comment créer des triangles en CSS en utilisant la propriété border-radius pour générer les angles. Aujourd'hui, essayons d'afficher des sphères.

Cet article est la traduction d'un article de Donovan Hutchinson publié sur http://hop.ie/blog/balls/ qui nous permettra d'examiner le processus de réalisation de sphères en pur CSS. Retrouvez toutes les traductions de hop.ie disponibles sur hop-ie.developpez.com.

Commentez

- Titre : Sphères en CSS3

- Auteur : Donovan Hutchinson

- Traducteur : rodolphebrd

- Parution : 5 août 2013

- Licence : Copyright ® 2013 Donovan Hutchinson. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- Structure de base

- Démo et code source

- Forme de base

- Technique d'ombrage

- Le dégradé radial

- Ombres et 3D

- Ombres multiples

- Effet de brillance

- Boule de billard N°8

- Œil en mouvement

- Bulle bondissante

- Utilisation d'images

- Globe terrestre animé

- Ressources

- Retours

- Remerciements

Structure de base

Nous pourrions aborder la réalisation de sphères en CSS de deux manières différentes.

La première consiste à créer une sphère 3D en utilisant beaucoup d'éléments. En voici de beaux exemples. L'inconvénient potentiel est que cela oblige le navigateur à afficher plusieurs éléments, pouvant avoir un impact sur les performances. Ces exemples laissent apparaître un lissage imparfait alors qu'une sphère lissée devrait nécessiter plusieurs éléments.

Nous essaierons une seconde approche en utilisant les dégradés en CSS (dégradé linéaire : linear-gradient et dégradé radial : radial-gradient) pour ajouter des ombrages et créer des effets 3D sur un élément unique.

Démo et code source

Tous les exemples de cet article peuvent être consultés sur mon compte Codepen ou grâce aux liens fournis après chaque exemple.

Forme de base

Avant de rentrer dans le vif du sujet, nous allons créer une forme initiale de sphère dont le code HTML est :

<figure class="circle"></figure>

Nous utiliserons ici l'élément <figure>, sachant que d'autres éléments peuvent être employés. L'élément <figure> est utilisé en HTML5 pour représenter une image ou un diagramme faisant partie du contenu et pouvant être supprimé sans altérer le sens de ce contenu.

Pour créer un cercle à partir de l'élément <figure>, nous définissons une largeur et une hauteur ainsi qu'un border-radius de 50 %. Toute valeur supérieure à 50 % donnera un résultat complètement arrondi.

.circle {
display: block;
background: black;
border-radius: 50%;
height: 300px;
width: 300px;
margin: 0;
}

Et un cercle apparaît.

Code HTML complet :

<figure class="circle"></figure>

Code CSS complet :

body {
width: 300px;
margin: 20px auto;
}
.circle {
display: block;
background: black;
border-radius: 100%;
height: 300px;
width: 300px;
margin: 0;
}

Exemple de la forme de base en ligne.

Maintenant que nous avons un cercle de base, nous pouvons commencer à y appliquer un style pour le transformer en quelque chose de plus sphérique.

Technique d'ombrage

Le principe de base consiste à ajouter un dégradé radial, légèrement en haut à gauche du centre du cercle.

Nous pouvons le faire en utilisant le code CSS suivant :

.circle {
display: block;
background: black;
border-radius: 50%;
height: 300px;
width: 300px;
margin: 0;
background: -webkit-radial-gradient(100px 100px, circle, #5cabff, #000);
background: -moz-radial-gradient(100px 100px, circle, #5cabff, #000);
background: radial-gradient(100px 100px, circle, #5cabff, #000);
}

Vous devriez obtenir ce résultat :

Code HTML complet :

<figure class="circle"></figure>

Code CSS complet :

body {
width: 300px;
margin: 20px auto;
}
.circle {
display: block;
background: black;
border-radius: 100%;
height: 300px;
width: 300px;
margin: 0;
background: -webkit-radial-gradient(100px 100px, circle, #5cabff, #000);
background: -moz-radial-gradient(100px 100px, circle, #5cabff, #000);
background: radial-gradient(100px 100px, circle, #5cabff, #000);
}

Exemple du dégradé radial en ligne.

Le dégradé radial

La propriété radial-gradient prend les valeurs suivantes : la première est la position (center par défaut) pour le départ du dégradé, ensuite la forme du dégradé est spécifiée (valeur : cercle ou ellipse), finalement une série de couleurs est définie. Vous pouvez définir plus de deux couleurs, mais il devient alors nécessaire d'inclure une distance entre chacune d'entre elles afin que la fonction (radial-gradient) sache à quel moment elle peut mélanger chaque couleur avec la suivante.

Dans l'exemple ci-dessus, seulement deux couleurs sont définies. Le navigateur suppose alors que la première est de 0 % et la suivante de 100 % de sorte qu'il affichera un dégradé entre ces deux couleurs. Si nous voulons des dégradés supplémentaires, nous pouvons définir des distances en pixel ou pourcentage, comme nous le verrons plus loin.

Nous avons donc un résultat se rapprochant d'une sphère en 3D. Même s'il semble correct nous allons tenter d'y apporter des améliorations.

Ombres et 3D

En fonction du choix de dégradé à appliquer, vous pouvez créer différents aspects de sphères. Dans un premier temps, nous allons définir un environnement pour y placer notre sphère.

Dans le code HTML nous ajoutons quelques éléments supplémentaires :

<section class="stage">
<figure class="ball"><span class="shadow"></span></figure>
</section>

L'élément « ball », placé dans l'élément « stage » (<section>), inclut un élément <span> qui sera utile pour créer une ombre. L'élément « stage » est utile lorsque nous voulons définir une perspective et positionner l'ombre afin de donner un effet 3D.

Appliquez quelques styles à l'élément « stage » et positionnez une ombre pour créer une scène :

.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
}
.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-radial-gradient(50% 50%, circle, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}

Notez que je n'inclus que la perspective avec le préfixe -webkit dans le code CSS. Les exemples ci-dessous contiennent tous les préfixes CSS. Dans l'exemple ci-dessus, une perspective d'une valeur de 1200 pixels est créée sur l'élément « stage ». La propriété perspective détermine le point de fuite dans une scène 3D.

L'ombre de la sphère est alors placée en lui définissant un dégradé radial, dégradé positionné par la propriété transform. La propriété CSS transform permet de manipuler dans l'espace 3D un élément HTML qui pourra subir des translations (translate), des rotations (rotate), des mises à l'échelle (scale) ou être inclinées (skew) selon les valeurs définies. L'ombre subit une rotation de 90 degrés sur l'axe des abscisses et descend de 150 pixels vers le bas pour apparaître à la base de la sphère.

Dès lors que nous avons défini une valeur à perspective pour le conteneur « stage », nous obtenons une vue du dessus qui nous permet de voir une forme ovale cintrée.

Code HTML complet :

<section class="stage">
<figure class="ball"><span class="shadow"></span></figure>
</section>

Code CSS complet :

.ball {
display: block;
background: black;
margin: 0;
border-radius: 50%;
height: 300px;
width: 300px;
background: -webkit-radial-gradient(100px 100px, circle, #5cabff, #000);
background: -moz-radial-gradient(100px 100px, circle, #5cabff, #000);
background: radial-gradient(100px 100px, circle, #5cabff, #000);
}
.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

Exemple d'ombres et 3D en ligne.

Le résultat devient meilleur. Dans le chapitre suivant, nous ajouterons plus d'ombres à l'élément « ball ».

Ombres multiples

Dans la réalité, vous trouverez très rarement des objets éclairés sous un seul angle. Les surfaces réfléchissent la lumière sur d'autres surfaces et il en résulte une variété de sources de lumière mélangées entre elles. Pour créer un effet plus réaliste nous allons considérer qu'il y a deux sources de lumière en utilisant des pseudoéléments afin d'ajouter deux dégradés.

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-radial-gradient(50% 120%, circle cover, #81e8f6, #76deef 10%, #055194 80%, #062745 100%);
);
}
.ball:before {
content: "";
position: absolute;
top: 1%;
left: 5%;
width: 90%;
height: 90%;
border-radius: 50%;
background: -webkit-radial-gradient(50% 0px, circle, #ffffff, rgba(255, 255, 255, 0) 58%);
-webkit-filter: blur(5px);
z-index: 2;
}

Comme d'habitude, je n'inclus que la version -webkit pour référence. Nous obtenons deux dégradés légèrement plus complexes.

Le premier dégradé est un subtil effet d'éclairage par le bas qui est appliqué à l'élément « ball ». Le centre du dégradé est positionné à 50 % de la largeur et 120 % de la hauteur. Le centre du dégradé se trouve ainsi placé en-dehors de la surface de la sphère. Le but étant de ne pas visualiser les contours de la couleur du dégradé (pouvant paraître brutale), adoucissant ainsi le dégradé.

Le deuxième dégradé (plus prononcé) est un éclairage, placé au-dessus. Il est défini à 90 % de la largeur et 90 % de la hauteur de la sphère. Le dégradé est centré au sommet de sorte qu'il diminue à partir de la moitié de la hauteur de la sphère.

Le pseudoélément :before est utilisé ici plutôt que de créer un nouvel élément qui contiendrait l'ombrage.

Dans la mesure où ce dégradé (plus prononcé) a des contours accentués, on peut, grâce à la propriété blur, créer un effet plus doux. À noter que cette propriété, fort utile, n'est valable pour l'instant que sur Chrome et Safari et doit être préfixée (-webkit-).

Les deux dégradés combinés produisent un résultat plus agréable :

Code HTML complet :

<section class="stage">
<figure class="ball"><span class="shadow"></span></figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-gradient(radial, 50% 120%, 0, 50% 120%, 100, color-stop(0%, #81e8f6), color-stop(10%, #76deef), color-stop(80%, #055194), color-stop(100%, #062745));
background: -webkit-radial-gradient(50% 120%, circle cover, #81e8f6, #76deef 10%, #055194 80%, #062745 100%);
background: -moz-radial-gradient(50% 120%, circle cover, #81e8f6, #76deef 10%, #055194 80%, #062745 100%);
background: -o-radial-gradient(50% 120%, circle cover, #81e8f6, #76deef 10%, #055194 80%, #062745 100%);
background: radial-gradient(50% 120%, circle cover, #81e8f6, #76deef 10%, #055194 80%, #062745 100%);
}
.ball:before {
content: "";
position: absolute;
top: 1%;
left: 5%;
width: 90%;
height: 90%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 0px, 0, 50% 0px, 58, color-stop(0%, #ffffff), color-stop(58%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
background: -moz-radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
background: -o-radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
background: radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
-webkit-filter: blur(5px);
z-index: 2;
}

.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

Exemple d'ombres multiples en ligne.

Effet de brillance

Jusqu'ici, les effets créés sont plutôt doux. Nous allons ajouter maintenant des effets de brillance et créer quelque chose se rapprochant d'une boule de billard.

Pour y parvenir, nous créerons un éclairage atténué par le bas, comme précédemment, mais nous ajusterons l'éclairage provenant du haut pour qu'il soit plus petit avec des contours plus prononcés. Nous aurons besoin d'utiliser deux pseudoéléments pour définir la couleur de la sphère, un éclairage par le bas et une réflexion.

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
}
.ball:before {
content: "";
position: absolute;
background: -webkit-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
border-radius: 50%;
bottom: 2.5%;
left: 5%;
opacity: 0.6;
height: 100%;
width: 90%;
-webkit-filter: blur(5px);
z-index: 2;
}
.ball:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 5%;
left: 10%;
border-radius: 50%;
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
-webkit-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-webkit-filter: blur(10px);
}

Nous avons, ici, appliqué un subtil dégradé avec la couleur initiale sur la sphère. Le pseudoélément :before permet de définir un éclairage plus prononcé qui démarre, une nouvelle fois, de la base de la sphère et crée l'effet d'un éclairage réfléchi par le sol.

Nous avons ajouté un nouveau pseudoélément :after permettant de créer un autre dégradé radial. Ce dégradé démarre avec une opacité de 0 % sur la couleur blanche et s'estompe jusqu'à une transparence de 24 %. On obtient un effet blanc brillant auquel on applique la propriété transform afin de donner l'impression de réflexion sur un objet en 3D.

La propriété transform déplace le reflet de 80 pixels vers la gauche et 90 pixels vers le haut avec une inclinaison (skew). La valeur skew rétrécit le cercle (de dégradé) selon l'axe des abscisses afin de rendre le reflet plus réaliste sur la boule brillante.

Code HTML complet :

<section class="stage">
<figure class="ball"><span class="shadow"></span></figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-gradient(radial, 50% 120%, 0, 50% 120%, 100, color-stop(0%, #323232), color-stop(80%, #0a0a0a), color-stop(100%, #000000));
background: -webkit-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
background: -moz-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
background: -o-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
background: radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
}
.ball:before {
content: "";
position: absolute;
background: -webkit-gradient(radial, 50% 120%, 0, 50% 120%, 70, color-stop(0%, rgba(255, 255, 255, 0.5)), color-stop(70%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
background: -moz-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
background: -o-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
background: radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
border-radius: 50%;
bottom: 2.5%;
left: 5%;
opacity: 0.6;
height: 100%;
width: 90%;
-webkit-filter: blur(5px);
z-index: 2;
}
.ball:after {
width: 100%;
height: 100%;
content: "";
position: absolute;
top: 5%;
left: 10%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 24, color-stop(0%, rgba(255, 255, 255, 0.8)), color-stop(14%, rgba(255, 255, 255, 0.8)), color-stop(24%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
-webkit-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-moz-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-ms-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-o-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-webkit-filter: blur(10px);
}

.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

Exemple d'effet de brillance en ligne

Boule de billard N°8

Voici les étapes pour ajouter le numéro 8 à notre boule de billard.

Nous créons pour cela un élément supplémentaire qui contiendra le 8, de même que nous définissons les styles correspondants.

<section class="stage">
<figure class="ball">
<span class="shadow"></span>
<span class="eight"></span>
</figure>
</section>

.ball .eight {
width: 110px;
height: 110px;
margin: 30%;
background: white;
border-radius: 50%;
-webkit-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
position: absolute;
}
.ball .eight:before {
content: "8";
display: block;
position: absolute;
text-align: center;
height: 80px;
width: 100px;
left: 50px;
margin-left: -40px;
top: 44px;
margin-top: -40px;
color: black;
font-family: Arial;
font-size: 90px;
line-height: 104px;
}

Le border-radius défini à 100 % est de nouveau utilisé pour créer un cercle qui est positionné en haut à droite grâce à la propriété transform (translate). Plutôt que de placer le numéro 8 dans le contenu, un pseudoélément :before est créé afin de le générer en CSS et de lui attribuer les mêmes transformations que le cercle blanc (contour du 8).

On obtient donc une boule de billard numérotée brillante :

Code HTML complet :

<section class="stage">
<figure class="ball">
<span class="shadow"></span>
<span class="eight"></span>
</figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-gradient(radial, 50% 120%, 0, 50% 120%, 100, color-stop(0%, #323232), color-stop(80%, #0a0a0a), color-stop(100%, #000000));
background: -webkit-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
background: -moz-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
background: -o-radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
background: radial-gradient(50% 120%, circle cover, #323232, #0a0a0a 80%, #000000 100%);
}
.ball:before {
content: "";
position: absolute;
background: -webkit-gradient(radial, 50% 120%, 0, 50% 120%, 70, color-stop(0%, rgba(255, 255, 255, 0.5)), color-stop(70%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
background: -moz-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
background: -o-radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
background: radial-gradient(50% 120%, circle cover, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 70%);
border-radius: 50%;
bottom: 2.5%;
left: 5%;
opacity: 0.6;
height: 100%;
width: 90%;
-webkit-filter: blur(5px);
z-index: 2;
}
.ball:after {
width: 100%;
height: 100%;
content: "";
position: absolute;
top: 5%;
left: 10%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 24, color-stop(0%, rgba(255, 255, 255, 0.8)), color-stop(14%, rgba(255, 255, 255, 0.8)), color-stop(24%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
-webkit-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-moz-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-ms-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-o-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-webkit-filter: blur(10px);
}
.ball .eight {
width: 110px;
height: 110px;
margin: 30%;
background: white;
border-radius: 50%;
-webkit-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-moz-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-ms-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-o-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
position: absolute;
}
.ball .eight:before {
content: "8";
display: block;
position: absolute;
text-align: center;
height: 80px;
width: 100px;
left: 50px;
margin-left: -40px;
top: 44px;
margin-top: -40px;
color: black;
font-family: Arial;
font-size: 90px;
line-height: 104px;
}

.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}

body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

Exemple de boule de billard en ligne.

Œil en mouvement

Une des grandes fonctionnalités de la propriété CSS transform consiste à créer des animations. Avec la règle CSS @keyframes, nous pouvons définir une série de transformations dans une animation et l'appliquer à un élément. Pour montrer cela, je vais créer et animer un œil.

La première étape consiste à modifier les couleurs définies précédemment dans notre boule de billard. Après quelques réglages on aura l'apparence d'un œil. Voici d'abord le code HTML :

<section class="stage">
<figure class="ball">
<span class="shadow"></span>
<span class="iris"></span>
</figure>
</section>

La majeure partie du code CSS est similaire à la boule de billard, excepté pour le traitement de l'iris et de la pupille :

.iris {
width: 40%;
height: 40%;
margin: 30%;
border-radius: 50%;
background: -webkit-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
-webkit-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
position: absolute;
-webkit-animation: move-eye-skew 5s ease-out infinite;
}
.iris:before {
content: "";
display: block;
position: absolute;
width: 37.5%;
height: 37.5%;
border-radius: 50%;
top: 31.25%;
left: 31.25%;
background: black;
}
.iris:after {
content: "";
display: block;
position: absolute;
width: 31.25%;
height: 31.25%;
border-radius: 50%;
top: 18.75%;
left: 18.75%;
background: rgba(255, 255, 255, 0.2);
}

Un dégradé bleu détermine la couleur de l'iris, la pupille et un reflet sur cette dernière sont créés à l'aide de pseudoéléments. Une animation est ajoutée sur l'iris au format suivant :

animation: animation-name 5s ease-out infinite;

Dans ce cas nous appliquerons une animation nommée « animation-name », définie pour durer 5 secondes, avec un nombre de répétitions infinies et une valeur « ease-out » pour l'effet de timing. La valeur ease-out permet de ralentir l'animation lorsqu'elle se termine afin d'obtenir un effet plus réaliste.

Sans l'animation décrite nous obtenons un œil particulièrement statique.

Code HTML complet :

<section class="stage">
<figure class="ball">
<span class="shadow"></span>
<span class="iris"></span>
</figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-gradient(radial, 50% 40%, 0, 50% 40%, 100, color-stop(0%, #fcfcfc), color-stop(66%, #efeff1), color-stop(100%, #9b5050));
background: -webkit-radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
background: -moz-radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
background: -o-radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
background: radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
}
.ball:after {
content: "";
position: absolute;
top: 5%;
left: 10%;
width: 100%;
height: 100%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 24, color-stop(0%, rgba(255, 255, 255, 0.8)), color-stop(14%, rgba(255, 255, 255, 0.8)), color-stop(24%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
-webkit-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-moz-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-ms-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-o-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
transform: translateX(-80px) translateY(-90px) skewX(-20deg);
}

.iris {
width: 40%;
height: 40%;
margin: 30%;
border-radius: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 100, color-stop(0%, #208ab4), color-stop(30%, #6fbfff), color-stop(100%, #4381b2));
background: -webkit-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
background: -moz-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
background: -o-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
background: radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
-webkit-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-moz-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-ms-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-o-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
position: absolute;
-webkit-animation: move-eye-skew 5s ease-out infinite;
-moz-animation: move-eye-skew 5s ease-out infinite;
-o-animation: move-eye-skew 5s ease-out infinite;
-ms-animation: move-eye-skew 5s ease-out infinite;
animation: move-eye-skew 5s ease-out infinite;
}
.iris:before {
content: "";
display: block;
position: absolute;
width: 37.5%;
height: 37.5%;
border-radius: 100%;
top: 31.25%;
left: 31.25%;
background: black;
}
.iris:after {
content: "";
display: block;
position: absolute;
width: 31.25%;
height: 31.25%;
border-radius: 100%;
top: 18.75%;
left: 18.75%;
background: rgba(255, 255, 255, 0.2);
}

.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

Exemple d'œil statique en ligne.

Déterminons les keyframes pour créer le mouvement de l'œil.

@-webkit-keyframes move-eye-skew {
0% {
-webkit-transform: none;
}
20% {
-webkit-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
}
25%, 44% {
-webkit-transform: none;
}
50%, 60% {
-webkit-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
}
66%, 100% {
-webkit-transform: none;
}
}

La règle CSS @keyframes peut paraître délicate à mettre en œuvre au premier abord. Il faut décrire les états de l'élément au cours des étapes (choisies) de l'animation, chaque état étant défini par un pourcentage. Dans ce cas l'animation de l'iris démarrera sans transformation. À 20 % (deuxième état) une transformation est appliquée afin de créer un déplacement et une inclinaison vers la gauche. L'espace entre le premier état (0 %) et le deuxième (20 %) est automatiquement calculé par le navigateur afin de créer une transition douce.

Le processus s'exécute tout au long des cinq états pour donner une animation d'une durée (spécifiée par animation-delay) de 5 secondes.

La version -webkit préfixée est intégrée ici, mais vous pourriez aussi bien vouloir créer des versions avec -moz, -ms et sans préfixe.

Le contenu dynamique ne peut pas être affiché dans ce support, veuillez consulter la page en ligne.

Code HTML complet :

<section class="stage">
<figure class="ball">
<span class="shadow"></span>
<span class="iris"></span>
</figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-gradient(radial, 50% 40%, 0, 50% 40%, 100, color-stop(0%, #fcfcfc), color-stop(66%, #efeff1), color-stop(100%, #9b5050));
background: -webkit-radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
background: -moz-radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
background: -o-radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
background: radial-gradient(50% 40%, circle cover, #fcfcfc, #efeff1 66%, #9b5050 100%);
}
.ball:after {
content: "";
position: absolute;
top: 5%;
left: 10%;
width: 100%;
height: 100%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 24, color-stop(0%, rgba(255, 255, 255, 0.8)), color-stop(14%, rgba(255, 255, 255, 0.8)), color-stop(24%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
background: radial-gradient(50% 50%, circle cover, rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8) 14%, rgba(255, 255, 255, 0) 24%);
-webkit-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-moz-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-ms-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
-o-transform: translateX(-80px) translateY(-90px) skewX(-20deg);
transform: translateX(-80px) translateY(-90px) skewX(-20deg);
}

.iris {
width: 40%;
height: 40%;
margin: 30%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 100, color-stop(0%, #208ab4), color-stop(30%, #6fbfff), color-stop(100%, #4381b2));
background: -webkit-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
background: -moz-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
background: -o-radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
background: radial-gradient(50% 50%, circle cover, #208ab4 0%, #6fbfff 30%, #4381b2 100%);
-webkit-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-moz-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-ms-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
-o-transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
transform: translateX(68px) translateY(-60px) skewX(15deg) skewY(2deg);
position: absolute;
-webkit-animation: move-eye-skew 5s ease-out infinite;
-moz-animation: move-eye-skew 5s ease-out infinite;
-o-animation: move-eye-skew 5s ease-out infinite;
-ms-animation: move-eye-skew 5s ease-out infinite;
animation: move-eye-skew 5s ease-out infinite;
}
.iris:before {
content: "";
display: block;
position: absolute;
width: 37.5%;
height: 37.5%;
border-radius: 50%;
top: 31.25%;
left: 31.25%;
background: black;
}
.iris:after {
content: "";
display: block;
position: absolute;
width: 31.25%;
height: 31.25%;
border-radius: 50%;
top: 18.75%;
left: 18.75%;
background: rgba(255, 255, 255, 0.2);
}

.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

@-moz-keyframes move-eye-skew {
0% {
-moz-transform: none;
transform: none; }

20% {
-moz-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95); }

25%, 44% {
-moz-transform: none;
transform: none; }

50%, 60% {
-moz-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95); }

66%, 100% {
-moz-transform: none;
transform: none; } }

@-webkit-keyframes move-eye-skew {
0% {
-webkit-transform: none;
transform: none; }

20% {
-webkit-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95); }

25%, 44% {
-webkit-transform: none;
transform: none; }

50%, 60% {
-webkit-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95); }

66%, 100% {
-webkit-transform: none;
transform: none; } }

@-o-keyframes move-eye-skew {
0% {
-o-transform: none;
transform: none; }

20% {
-o-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95); }

25%, 44% {
-o-transform: none;
transform: none; }

50%, 60% {
-o-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95); }

66%, 100% {
-o-transform: none;
transform: none; } }

@-ms-keyframes move-eye-skew {
0% {
-ms-transform: none;
transform: none; }

20% {
-ms-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95); }

25%, 44% {
-ms-transform: none;
transform: none; }

50%, 60% {
-ms-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95); }

66%, 100% {
-ms-transform: none;
transform: none; } }

@keyframes move-eye-skew {
0% {
-webkit-transform: none;
-moz-transform: none;
-ms-transform: none;
-o-transform: none;
transform: none; }

20% {
-webkit-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
-moz-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
-ms-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
-o-transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95);
transform: translateX(-68px) translateY(30px) skewX(15deg) skewY(-10deg) scale(0.95); }

25%, 44% {
-webkit-transform: none;
-moz-transform: none;
-ms-transform: none;
-o-transform: none;
transform: none; }

50%, 60% {
-webkit-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
-moz-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
-ms-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
-o-transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95);
transform: translateX(68px) translateY(-40px) skewX(5deg) skewY(2deg) scaleX(0.95); }

66%, 100% {
-webkit-transform: none;
-moz-transform: none;
-ms-transform: none;
-o-transform: none;
transform: none; } }

Exemple d'œil en mouvement en ligne.

Bulle bondissante

En utilisant une combinaison d'ombrages et d'animations, nous pouvons produire toutes sortes d'effets, comme la réalisation d'une bulle qui rebondit.

Cette création est similaire à l'exemple précédent (œil en mouvement) sachant que nous utiliserons plus de transparence pour la couleur principale ainsi que deux pseudoéléments pour les reflets.

L'animation utilisera la fonction scale (mise à l'échelle) pour créer une déformation de l'ensemble de la bulle lors du rebond.

@-webkit-keyframes bubble-anim {
0% {
-webkit-transform: scale(1);
}
20% {
-webkit-transform: scaleY(0.95) scaleX(1.05);
}
48% {
-webkit-transform: scaleY(1.1) scaleX(0.9);
}
68% {
-webkit-transform: scaleY(0.98) scaleX(1.02);
}
80% {
-webkit-transform: scaleY(1.02) scaleX(0.98);
}
97%, 100% {
-webkit-transform: scale(1);
}
}

L'animation est appliquée à la totalité de la bulle et ses pseudoéléments.

Le contenu dynamique ne peut pas être affiché dans ce support, veuillez consulter la page en ligne.

Code HTML complet :

<section class="stage">
<figure class="ball"></figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: -webkit-gradient(radial, 50% 55%, 0, 50% 55%, 100, color-stop(0%, rgba(240, 245, 255, 0.9)), color-stop(40%, rgba(240, 245, 255, 0.9)), color-stop(60%, rgba(225, 238, 255, 0.8)), color-stop(100%, rgba(43, 130, 255, 0.4)));
background: -webkit-radial-gradient(50% 55%, circle cover, rgba(240, 245, 255, 0.9), rgba(240, 245, 255, 0.9) 40%, rgba(225, 238, 255, 0.8) 60%, rgba(43, 130, 255, 0.4));
background: -moz-radial-gradient(50% 55%, circle cover, rgba(240, 245, 255, 0.9), rgba(240, 245, 255, 0.9) 40%, rgba(225, 238, 255, 0.8) 60%, rgba(43, 130, 255, 0.4));
background: -o-radial-gradient(50% 55%, circle cover, rgba(240, 245, 255, 0.9), rgba(240, 245, 255, 0.9) 40%, rgba(225, 238, 255, 0.8) 60%, rgba(43, 130, 255, 0.4));
background: radial-gradient(50% 55%, circle cover, rgba(240, 245, 255, 0.9), rgba(240, 245, 255, 0.9) 40%, rgba(225, 238, 255, 0.8) 60%, rgba(43, 130, 255, 0.4));
-webkit-animation: bubble-anim 2s ease-out infinite;
-moz-animation: bubble-anim 2s ease-out infinite;
-o-animation: bubble-anim 2s ease-out infinite;
-ms-animation: bubble-anim 2s ease-out infinite;
animation: bubble-anim 2s ease-out infinite;
}
.ball:before {
/* Sheen on the bottom right */
content: "";
position: absolute;
top: 1%;
left: 5%;
width: 90%;
height: 90%;
border-radius: 50%;
-webkit-filter: blur(0);
height: 80%;
width: 40%;
background: -webkit-gradient(radial, 130% 130%, 0, 130% 130%, 100, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(46%, rgba(255, 255, 255, 0)), color-stop(50%, rgba(255, 255, 255, 0.8)), color-stop(58%, rgba(255, 255, 255, 0.8)), color-stop(60%, rgba(255, 255, 255, 0)), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(130% 130%, circle, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0.8) 58%, rgba(255, 255, 255, 0) 60%, rgba(255, 255, 255, 0) 100%);
background: -moz-radial-gradient(130% 130%, circle, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0.8) 58%, rgba(255, 255, 255, 0) 60%, rgba(255, 255, 255, 0) 100%);
background: -o-radial-gradient(130% 130%, circle, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0.8) 58%, rgba(255, 255, 255, 0) 60%, rgba(255, 255, 255, 0) 100%);
background: radial-gradient(130% 130%, circle, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 46%, rgba(255, 255, 255, 0.8) 50%, rgba(255, 255, 255, 0.8) 58%, rgba(255, 255, 255, 0) 60%, rgba(255, 255, 255, 0) 100%);
-webkit-transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg);
-moz-transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg);
-ms-transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg);
-o-transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg);
transform: translateX(131%) translateY(58%) rotateZ(168deg) rotateX(10deg);
}
.ball:after {
/* Top left highlight */
content: "";
position: absolute;
top: 5%;
left: 10%;
width: 80%;
height: 80%;
border-radius: 100%;
background: -webkit-gradient(radial, 50% 80%, 0, 50% 80%, 100, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(74%, rgba(255, 255, 255, 0)), color-stop(80%, #ffffff), color-stop(84%, #ffffff), color-stop(100%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 80%, circle cover, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 74%, #ffffff 80%, #ffffff 84%, rgba(255, 255, 255, 0) 100%);
background: -moz-radial-gradient(50% 80%, circle cover, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 74%, #ffffff 80%, #ffffff 84%, rgba(255, 255, 255, 0) 100%);
background: -o-radial-gradient(50% 80%, circle cover, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 74%, #ffffff 80%, #ffffff 84%, rgba(255, 255, 255, 0) 100%);
background: radial-gradient(50% 80%, circle cover, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0) 74%, #ffffff 80%, #ffffff 84%, rgba(255, 255, 255, 0) 100%);
opacity: 0.6;
-webkit-filter: blur(1px);
z-index: 2;
-webkit-transform: rotateZ(-30deg);
-moz-transform: rotateZ(-30deg);
-ms-transform: rotateZ(-30deg);
-o-transform: rotateZ(-30deg);
transform: rotateZ(-30deg);
}
.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

@-moz-keyframes bubble-anim {
0% {
-moz-transform: scale(1);
transform: scale(1); }

20% {
-moz-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-moz-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-moz-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-moz-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-moz-transform: scale(1);
transform: scale(1); } }

@-webkit-keyframes bubble-anim {
0% {
-webkit-transform: scale(1);
transform: scale(1); }

20% {
-webkit-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-webkit-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-webkit-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-webkit-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-webkit-transform: scale(1);
transform: scale(1); } }

@-o-keyframes bubble-anim {
0% {
-o-transform: scale(1);
transform: scale(1); }

20% {
-o-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-o-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-o-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-o-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-o-transform: scale(1);
transform: scale(1); } }

@-ms-keyframes bubble-anim {
0% {
-ms-transform: scale(1);
transform: scale(1); }

20% {
-ms-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-ms-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-ms-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-ms-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-ms-transform: scale(1);
transform: scale(1); } }

@keyframes bubble-anim {
0% {
transform: scale(1); }

20% {
transform: scaleY(0.95) scaleX(1.05); }

48% {
transform: scaleY(1.1) scaleX(0.9); }

68% {
transform: scaleY(0.98) scaleX(1.02); }

80% {
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
transform: scale(1); } }

Exemple de bulle bondissante en ligne.

Utilisation d'images

Jusqu'ici, nous avons créé des sphères sans utiliser d'images. Appliquer des images en arrière-plan permet d'ajouter plus de détails tout en profitant de l'avantage que nous apporte la création d'ombres en CSS par l'intermédiaire des pseudoéléments. Voici par exemple une texture de balle de tennis sans effets d'ombre.

En ajoutant des dégradés par l'intermédiaire des CSS nous créons une illusion de profondeur :

Code HTML complet :

<section class="stage">
<figure class="ball"><span class="shadow"></span></figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
background: url(http://hop.ie/balls/images/tennisball.png) no-repeat;
background-size: 100%;
}
.ball:before {
content: "";
position: absolute;
top: 1%;
left: 5%;
width: 90%;
height: 90%;
border-radius: 50%;
background: -webkit-gradient(radial, 50% 0px, 0, 50% 0px, 58, color-stop(0%, #ffffff), color-stop(58%, rgba(255, 255, 255, 0)));
background: -webkit-radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
background: -moz-radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
background: -o-radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
background: radial-gradient(50% 0px, circle cover, #ffffff, rgba(255, 255, 255, 0) 58%);
-webkit-filter: blur(5px);
z-index: 2;
}
.ball:after {
content: "";
position: absolute;
border-radius: 100%;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: -webkit-gradient(radial, 50% 30%, 0, 50% 30%, 100, color-stop(0%, rgba(245, 237, 48, 0)), color-stop(50%, rgba(200, 190, 20, 0.2)), color-stop(100%, #575300));
background: -webkit-radial-gradient(50% 30%, circle cover, rgba(245, 237, 48, 0), rgba(200, 190, 20, 0.2) 50%, #575300 100%);
background: -moz-radial-gradient(50% 30%, circle cover, rgba(245, 237, 48, 0), rgba(200, 190, 20, 0.2) 50%, #575300 100%);
background: -o-radial-gradient(50% 30%, circle cover, rgba(245, 237, 48, 0), rgba(200, 190, 20, 0.2) 50%, #575300 100%);
background: radial-gradient(50% 30%, circle cover, rgba(245, 237, 48, 0), rgba(200, 190, 20, 0.2) 50%, #575300 100%);
}

.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}

body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

@-moz-keyframes bubble-anim {
0% {
-moz-transform: scale(1);
transform: scale(1); }

20% {
-moz-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-moz-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-moz-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-moz-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-moz-transform: scale(1);
transform: scale(1); } }

@-webkit-keyframes bubble-anim {
0% {
-webkit-transform: scale(1);
transform: scale(1); }

20% {
-webkit-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-webkit-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-webkit-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-webkit-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-webkit-transform: scale(1);
transform: scale(1); } }

@-o-keyframes bubble-anim {
0% {
-o-transform: scale(1);
transform: scale(1); }

20% {
-o-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-o-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-o-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-o-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-o-transform: scale(1);
transform: scale(1); } }

@-ms-keyframes bubble-anim {
0% {
-ms-transform: scale(1);
transform: scale(1); }

20% {
-ms-transform: scaleY(0.95) scaleX(1.05);
transform: scaleY(0.95) scaleX(1.05); }

48% {
-ms-transform: scaleY(1.1) scaleX(0.9);
transform: scaleY(1.1) scaleX(0.9); }

68% {
-ms-transform: scaleY(0.98) scaleX(1.02);
transform: scaleY(0.98) scaleX(1.02); }

80% {
-ms-transform: scaleY(1.02) scaleX(0.98);
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
-ms-transform: scale(1);
transform: scale(1); } }

@keyframes bubble-anim {
0% {
transform: scale(1); }

20% {
transform: scaleY(0.95) scaleX(1.05); }

48% {
transform: scaleY(1.1) scaleX(0.9); }

68% {
transform: scaleY(0.98) scaleX(1.02); }

80% {
transform: scaleY(1.02) scaleX(0.98); }

97%, 100% {
transform: scale(1); } }

Exemple de balle de tennis en ligne.

Globe terrestre animé

Les animations peuvent aussi être appliquées sur la position d'une image placée en arrière-plan. Par ce moyen, nous pouvons réaliser un globe terrestre en rotation.

L'image utilisée a été rétrécie au sommet et en bas pour être utilisée en arrière-plan  :

Avec un complément composé d'ombrage et d'animation, un globe style 3D peut être créé. Voici le résultat en action : globe terrestre 1 en ligne.
L'exemple n'est pas affiché directement sur cette page parce que les performances sur cet exemple sont assez médiocres, ce qui a entraîné un emballement du ventilateur sur mon portable.

Code HTML complet :

<section class="stage">
<figure class="ball"><span class="shadow"></span></figure>
</section>

Code CSS complet :

.ball {
display: inline-block;
width: 100%;
height: 100%;
margin: 0;
border-radius: 50%;
position: relative;
-webkit-transform-style: preserve-3d;
background: url('http://hop.ie/balls/images/world-map-one-color.png') repeat-x;
background-size: auto 100%;
-webkit-animation: move-map 30s infinite linear;
-moz-animation: move-map 30s infinite linear;
-o-animation: move-map 30s infinite linear;
-ms-animation: move-map 30s infinite linear;
animation: move-map 30s infinite linear;
}

.ball:before {
content: "";
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 100%;
border-radius: 50%;
box-shadow: -40px 10px 70px 10px rgba(0,0,0,0.5) inset;
z-index: 2;
}

.ball:after {
content: "";
position: absolute;
border-radius: 50%;
width: 100%;
height: 100%;
top: 0;
left: 0;
-webkit-filter: blur(0);
opacity: 0.3;
background: -webkit-gradient(radial, 50% 80%, 0, 50% 80%, 100, color-stop(0%, #81e8f6), color-stop(10%, #76deef), color-stop(66%, #055194), color-stop(100%, #062745));
background: -webkit-radial-gradient(50% 80%, circle cover, #81e8f6, #76deef 10%, #055194 66%, #062745 100%);
background: -moz-radial-gradient(50% 80%, circle cover, #81e8f6, #76deef 10%, #055194 66%, #062745 100%);
background: -o-radial-gradient(50% 80%, circle cover, #81e8f6, #76deef 10%, #055194 66%, #062745 100%);
background: radial-gradient(50% 80%, circle cover, #81e8f6, #76deef 10%, #055194 66%, #062745 100%);
}

.ball .shadow {
position: absolute;
width: 100%;
height: 100%;
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 50, color-stop(0%, rgba(0, 0, 0, 0.4)), color-stop(40%, rgba(0, 0, 0, 0.1)), color-stop(50%, rgba(0, 0, 0, 0)));
background: -webkit-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -moz-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: -o-radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
background: radial-gradient(50% 50%, circle cover, rgba(0, 0, 0, 0.4), rgba(0, 0, 0, 0.1) 40%, rgba(0, 0, 0, 0) 50%);
-webkit-transform: rotateX(90deg) translateZ(-150px);
-moz-transform: rotateX(90deg) translateZ(-150px);
-ms-transform: rotateX(90deg) translateZ(-150px);
-o-transform: rotateX(90deg) translateZ(-150px);
transform: rotateX(90deg) translateZ(-150px);
z-index: -1;
}
body {
width: 300px;
margin: 20px auto;
background: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, rgba(100, 100, 100, 0.2)), color-stop(40%, rgba(255, 255, 255, 0.5)), color-stop(100%, #ffffff));
background: -webkit-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -moz-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: -o-linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background: linear-gradient(top, rgba(100, 100, 100, 0.2) 0%, rgba(255, 255, 255, 0.5) 40%, #ffffff 100%);
background-repeat: no-repeat;
}

.stage {
width: 300px;
height: 300px;
display: inline-block;
margin: 20px;
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-ms-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
-webkit-perspective-origin: 50% 50%;
-moz-perspective-origin: 50% 50%;
-ms-perspective-origin: 50% 50%;
-o-perspective-origin: 50% 50%;
perspective-origin: 50% 50%;
}

@-moz-keyframes move-map {
0% {
background-position: -849px 0; }

100% {
background-position: 0 0; } }

@-webkit-keyframes move-map {
0% {
background-position: 0 0; }
100% {
background-position: -849px 0; }
}

@-o-keyframes move-map {
0% {
background-position: -849px 0; }

100% {
background-position: 0 0; } }

@-ms-keyframes move-map {
0% {
background-position: -849px 0; }

100% {
background-position: 0 0; } }

@keyframes move-map {
0% {
background-position: -849px 0; }

100% {
background-position: 0 0; } }

Code JS :

/*

THANK YOU to Sidoruk Sergey ?@Sidoruk_SV for upgrading this globe! Looks really good!

His original is here: http://codepen.io/anon/pen/ctKrk

*/

Note : un grand merci à Sidoruk Sergey (@Sidoruk_SV) pour avoir mis à niveau ce globe. C'est du beau boulot. (NdT : voir l'exemple globe terrestre 2 en ligne).

Ressources

Quelques bonnes infos concernant le dégradé radial au cas où vous aimeriez en savoir plus.

À la recherche de plus d'exemples 3D ? Jetez un coup d'œil sur Zelda - Un lien vers les CSS ou mon Portail CSS pour plus d'inspiration.

Retours

Tous les exemples mentionnés peuvent être retrouvés via mon compte Codepen. Un grand merci à Chris et l'équipe pour avoir fait en sorte que ce soit une fantastique ressource.

Si vous avez des questions concernant l'article, contactez-moi par mail ou sur Twitter.

Remerciements

Nous tenons à remercier Donovan Hutchinson pour nous avoir autorisé à traduire cet article dont vous retrouverez l'original ici : http://hop.ie/blog/balls/.

Remerciements à rodolphebrd pour la traduction de cet article, à ced pour sa relecture orthographique et à 12monkeys et Bovino pour leur relecture complète et minutieuse.