Présentation

Image non disponible
Voir une démo en ligne

Voir une démo en ligne.

Téléchargez l'archive de l'exemple.

Cet exemple fonctionne avec :
Webkit Mozilla Trident Presto
Oui Oui Oui Pas d'animation

Fonctionnement

De façon basique, j'ai utilisé un ensemble de balises <div> et les ai mises dans un conteneur global. Chaque div interne ayant une taille définie selon un pourcentage du conteneur et animé de façon à en changer l'opacité. Cela semble facile non ? En tout cas, cela l'aurait été si changer la position d'un élément avait été plus simple et si une propriété comme animation existait dans les navigateurs, ou si au moins, en la définissant, le navigateur était capable d'ajouter son propre préfixe automatiquement, ce qui aurait évité d'utiliser -moz-, -webkit- et -ms-.

L'une de mes pires déceptions en créant cette animation a été de me rendre compte qu'elle ne fonctionnerait pas avec Opera. J'ai pourtant tout essayé, mais comme il ne supporte pas les animations, cela ressemblera plus à une roue bizarre qu'à une animation de chargement avec ce navigateur.
Mais passons au code. Voici à quoi ressemble la structure HTML :

 
Sélectionnez

<div class="spinner">
    <div class="piece a"> </div>
    <div class="piece b"> </div>
    <div class="piece c"> </div>
    <div class="piece d"> </div>
    <div class="piece e"> </div>
    <div class="piece f"> </div>
    <div class="piece g"> </div>
    <div class="piece h"> </div>
    <div class="piece i"> </div>
    <div class="piece j"> </div>
    <div class="piece k"> </div>
    <div class="piece l"> </div>
    <div class="piece m"> </div>
    <div class="piece n"> </div>
    <div class="piece o"> </div>
    <div class="piece p"> </div>
</div>

Quant au CSS, le voici :

 
Sélectionnez

.spinner {
    width: 32px;
    height: 32px;
}
 
.piece {
    background: #000;
    width: 50%;
    height: 14%;
    position: relative;
}
 
.spinner div {
    opacity: 0.2;
}
 
@-webkit-keyframes fade {
 
    5% { opacity: 0.8; }
    30% { opacity: 0.5; }
 
}
@-ms-keyframes fade {
 
    5% { opacity: 0.8; }
    30% { opacity: 0.5; }
 
}
@-moz-keyframes fade {
 
    5% { opacity: 0.8; }
    30% { opacity: 0.5; }
 
}
 
.a, .p {
    height: 50%;
    width: 14%;
    left: 99%;
}
 
.a {
    top: 5%;
    -webkit-animation: fade 3.2s ease-in infinite;
    -moz-animation: fade 3.2s ease-in infinite;
    -ms-animation: fade 3.2s ease-in infinite;
}
 
.b {
    bottom: 21%;
    left: 50%;
    -webkit-animation: fade 3.2s ease-in-out 3s infinite;
    -moz-animation: fade 3.2s ease-in-out 3s infinite;
    -ms-animation: fade 3.2s ease-in-out 3s infinite;
}
 
.c {
    bottom: 34%;
    left: 110%;
    -webkit-animation: fade 3.2s ease-in-out 0.2s infinite;
    -moz-animation: fade 3.2s ease-in-out 0.2s infinite;
    -ms-animation: fade 3.2s ease-in-out 0.2s infinite;
}
 
.d {
    bottom: 31%;
    left: 27%;
    -webkit-animation: fade 3.2s ease-in-out 2.8s infinite;
    -moz-animation: fade 3.2s ease-in-out 2.8s infinite;
    -ms-animation: fade 3.2s ease-in-out 2.8s infinite;
}
 
.e {
    bottom: 43%;
    left: 134%;
    -webkit-animation: fade 3.2s ease-in-out 0.4s infinite;
    -moz-animation: fade 3.2s ease-in-out 0.4s infinite;
    -ms-animation: fade 3.2s ease-in-out 0.4s infinite;
}
 
.f {
    bottom: 32%;
    left: 11%;
    -webkit-animation: fade 3.2s ease-in-out 2.6s infinite;
    -moz-animation: fade 3.2s ease-in-out 2.6s infinite;
    -ms-animation: fade 3.2s ease-in-out 2.6s infinite;
}
 
.g {
    bottom: 45%;
    left: 149%;
    -webkit-animation: fade 3.2s ease-in-out 0.6s infinite;
    -moz-animation: fade 3.2s ease-in-out 0.6s infinite;
    -ms-animation: fade 3.2s ease-in-out 0.6s infinite;
}
 
.h {
    bottom: 30%;
    left: 6%;
    -webkit-animation: fade 3.2s ease-in-out 2.4s infinite;
    -moz-animation: fade 3.2s ease-in-out 2.4s infinite;
    -ms-animation: fade 3.2s ease-in-out 2.4s infinite;
}
 
.i {
    bottom: 43%;
    left: 155%;
    -webkit-animation: fade 3.2s ease-in-out 0.8s infinite;
    -moz-animation: fade 3.2s ease-in-out 0.8s infinite;
    -ms-animation: fade 3.2s ease-in-out 0.8s infinite;
}
.j {
    bottom: 29%;
    left: 12%;
    -webkit-animation: fade 3.2s ease-in-out 2.2s infinite;
    -moz-animation: fade 3.2s ease-in-out 2.2s infinite;
    -ms-animation: fade 3.2s ease-in-out 2.2s infinite;
}
 
.k {
    left: 149%;
    bottom: 41%;
    -webkit-animation: fade 3.2s ease-in-out 1s infinite;
    -moz-animation: fade 3.2s ease-in-out 1s infinite;
    -ms-animation: fade 3.2s ease-in-out 1s infinite;
}
 
.l {
    bottom: 30%;
    left: 28%;
    -webkit-animation: fade 3.2s ease-in-out 2s infinite;
    -moz-animation: fade 3.2s ease-in-out 2s infinite;
    -ms-animation: fade 3.2s ease-in-out 2s infinite;
}
 
.m {
    bottom: 43%;
    left: 134%;
    -webkit-animation: fade 3.2s ease-in-out 1.2s infinite;
    -moz-animation: fade 3.2s ease-in-out 1.2s infinite;
    -ms-animation: fade 3.2s ease-in-out 1.2s infinite;
}
 
.n {
    bottom: 40%;
    left: 50%;
    -webkit-animation: fade 3.2s ease-in-out 1.8s infinite;
    -moz-animation: fade 3.2s ease-in-out 1.8s infinite;
    -ms-animation: fade 3.2s ease-in-out 1.8s infinite;
}
 
.o {
    left: 110%;
    bottom: 52%;
    -webkit-animation: fade 3.2s ease-in-out 1.4s infinite;
    -moz-animation: fade 3.2s ease-in-out 1.4s infinite;
    -ms-animation: fade 3.2s ease-in-out 1.4s infinite;
}
.p {
    bottom: 78%;
    -webkit-animation: fade 3.2s ease-in-out 1.6s infinite;
    -moz-animation: fade 3.2s ease-in-out 1.6s infinite;
    -ms-animation: fade 3.2s ease-in-out 1.6s infinite;
}
 
.b, .o {
    -webkit-transform: rotate(67.5deg);
    -moz-transform: rotate(67.5deg);
    -ms-transform: rotate(67.5deg);
    -o-transform: rotate(67.5deg);
}
 
.d, .m {
    -webkit-transform: rotate(45deg);
    -moz-transform: rotate(45deg);
    -ms-transform: rotate(45deg);
    -o-transform: rotate(45deg);
}
 
.f, .k {
    -webkit-transform: rotate(22.5deg);
    -moz-transform: rotate(22.5deg);
    -ms-transform: rotate(22.5deg);
    -o-transform: rotate(22.5deg);
 
}
 
.n, .c {
    -webkit-transform: rotate(-67.5deg);
    -moz-transform: rotate(-67.5deg);
    -ms-transform: rotate(-67.5deg);
    -o-transform: rotate(-67.5deg);}
 
.l, .e {
    -webkit-transform: rotate(-45deg);
    -moz-transform: rotate(-45deg);
    -ms-transform: rotate(-45deg);
    -o-transform: rotate(-45deg);
}
 
.j, .g {
    -webkit-transform: rotate(-22.5deg);
    -moz-transform: rotate(-22.5deg);
    -ms-transform: rotate(-22.5deg);
    -o-transform: rotate(-22.5deg);
}

Je pourrais passer du temps à expliquer tout cela, mais de façon simple, j'ai juste fait pivoter mon paquet de div et utilisé des transformations pour les faire ressembler à une roue. Puis j'ai ajouté quelques animations simples pour faire un fondu sur chaque rayon au bon moment, j'ai enfin appliqué ces animations avec des retards adaptés pour que le rendu soit correct. Si vous voulez plus de détails sur les animations, vous pouvez lire mon article à ce sujet.

Puisque j'ai utilisé des valeurs en pourcentage (mon coup de génie), vous pouvez changer les dimensions de la classe .spinner et l'ensemble sera impacté. Mais rappelez-vous que la taille indiquée ne correspond pas à la taille de l'animation, elle sera plus grande. Notez au passage que le CSS compressé fait environ 4 ko, ce qui est moins que la plupart des fichiers gif que l'on trouve habituellement. Bien sûr, ce n'est peut-être pas encore une solution idéale, puisqu'elle n'est pas supportée à 100 %, mais espérons que ça le sera un jour.

Voir une démo en ligne.

Téléchargez l'archive de l'exemple.

Conclusion et remerciements

C'est terminé. Si cet article vous a plu, n'hésitez pas à le commenter et à proposer vos idées d'améliorations. (NDT Y compris sur le site de l'article original.)

Cet article a été publié avec l'aimable autorisation de Johnny Simpson. L'article original peut être lu sur le site de inserthtml : Making a Loading Icon in just CSS!.

Nous tenons aussi à remercier ClaudeLELOUP pour sa relecture attentive de cet article.