Contenu principal
Icône Cloud en CSS

Une icône Cloud en CSS

Depuis quelques temps, on parle de plus en plus du « Cloud », à tel point que petit à petit, les nuages fleurissent partout sur le web. Et bien pourquoi ne pas rentrer dans la mouvance et créer notre petit nuage personnel en CSS? Bien sûr en CSS3, sans tenir compte de Celui-Dont-On-Ne-Doit-Pas-Prononcer-Le-Nom.

J’ai essayé trois façons différentes pour faire notre icône, avec plus ou moins de succès au niveau du rendu final. Je vais vous en montrer qu’une mais les trois sont incluses dans le zip téléchargeable et dans la démo. Celle que nous allons voir ici est la plus compliquée des trois, mais c’est celle qui donne les meilleurs résultats, le plus dur à réaliser étant la flèche, c’est là où les trois méthodes diffèrent.

Balisage HTML

Nous aurons besoin de 4 div imbriquées : .download pour le fond noir transparent, .cloud pour le nuage, .cloud-arrow pour les bordures de la flèche, et .cloud-mask pour la flèche blanche.

1234567
<div class="download">
	<div class="cloud">
		<div class="cloud-arrow">
			<div class="cloud-mask"></div>
		</div>
	</div>
</div>

Le fond de l’icône

12345678
.download {
	position: relative;
	width: 100px;
	height: 100px;
	margin: 0 auto;
	border-radius: 14px;
	background: rgba(0,0,0,.7);
}

Pour le positionnement et le margin, vous rectifierez par vous-même selon les besoins ;)

Le nuage

Pour le reste, tous nos éléments seront positionnés en absolute et auront un fond blanc (ou presque tous). Nous utiliserons aussi les pseudo-éléments :before et :after :

09101112
.cloud, .cloud:before, .cloud:after, .cloud-arrow, .cloud-arrow:before, .cloud-arrow:after, .cloud-mask, .cloud-mask:before, .cloud-mask:after {
	position: absolute;
	background: #fff;
}

Creation du nuage
Voilà comment nous allons construire notre nuage :
La partie blanche est seulement un rectangle avec les coins arrondis, le rond représenté en rouge est le pseudo-élément :before, et le rond vert est le pseudo-élément :after. Nous devons juste faire attention au z-index car la flèche devra être au-dessus des deux ronds du nuage.

13141516171819202122232425262728293031323334353637
.cloud {
	width: 80px;
	height: 30px;
	left: 10px;
	top: 42px;
	border-radius: 15px;
}
.cloud:before {
	content:'';
	width: 20px;
	height: 22px;
	left: 13px;
	top: -12px;
	border-radius: 10px;
	z-index: 20;
}
.cloud:after {
	content:'';
	width: 40px;
	height: 40px;
	right: 13px;
	top: -21px;
	border-radius: 20px;
	z-index: 20;
}

Le fond de la flèche

Avec .cloud-arrow nous allons faire la barre verticale de la flèche : fond blanc, bordure de 2px et coins arrondis (et un z-index de 30, supérieur aux ronds du nuage).

383940414243444546
.cloud-arrow {
	width: 12px;
	height: 15px;
	left: 32px;
	top: 7px;
	border-radius: 3px;
	border: solid 2px rgb(50,50,50);
	z-index: 30;
}

Bordure de la pointeC’est maintenant que ça se complique. Avec :before et :after nous allons créer les bords gauche et droit de la pointe. Pour (essayer de) faire simple, prenons le bord gauche pour exemple (:before) :
Avec linear-gradient on applique un fond gris jusqu’à 50% de la largeur (en rouge sur l’image) et transparent sur le reste (en vert sur l’image), puis on incline ce fond de 45° vers le bas. On obtient alors un triangle gris pointant vers le haut et la gauche.
Puis, avec skewX(), on déforme le tout comme si on tirait le haut du triangle vers la gauche. On obtient donc un triangle plus fin. Ces manipulation nous permettent, entre autres, d’avoir un coin supérieur gauche arrondi.

Enfin, avec :after on fait la même chose mais dans l’autre sens.

474849505152535455565758596061626364656667686970717273747576777879
.cloud-arrow:before, .cloud-arrow:after {
	content:'';
	width: 19px;
	height: 17px;
	bottom: -16px;
	z-index: 40;
}
.cloud-arrow:before {
	right: -5px;
	border-top-left-radius: 4px;
	-webkit-transform:	skewX(40deg);
	-moz-transform:		skewX(40deg);
	-o-transform:		skewX(40deg);
	transform:		skewX(40deg);
	background: transparent -webkit-gradient(linear, 0 0, 19 19, from(rgb(50,50,50)), to(transparent), color-stop(0.5, rgb(50,50,50)), color-stop(0.5, transparent));
	background: transparent -webkit-linear-gradient(-45deg, rgb(50,50,50) 50%, transparent 50%);
	background: transparent    -moz-linear-gradient(-45deg, rgb(50,50,50) 50%, transparent 50%);
	background: transparent      -o-linear-gradient(-45deg, rgb(50,50,50) 50%, transparent 50%);
	background: transparent         linear-gradient(-45deg, rgb(50,50,50) 50%, transparent 50%);
}
.cloud-arrow:after {
	left: -5px;
	border-top-right-radius: 4px;
	-webkit-transform:	skewX(-40deg);
	-moz-transform:		skewX(-40deg);
	-o-transform:		skewX(-40deg);
	transform:		skewX(-40deg);
	background: transparent -webkit-gradient(linear, 19 0, 0 19, from(rgb(50,50,50)), to(transparent), color-stop(0.5, rgb(50,50,50)), color-stop(0.5, transparent));
	background: transparent -webkit-linear-gradient(-135deg, rgb(50,50,50) 50%, transparent 50%);
	background: transparent    -moz-linear-gradient(-135deg, rgb(50,50,50) 50%, transparent 50%);
	background: transparent      -o-linear-gradient(-135deg, rgb(50,50,50) 50%, transparent 50%);
	background: transparent         linear-gradient(-135deg, rgb(50,50,50) 50%, transparent 50%);
}

La partie blanche de la flèche

Maintenant il nous faut créer la partie blanche de la pointe, mais aussi masquer la bordure haute grise de la pointe (sinon on obtient une sorte de « maison » à l’envers).
Avec .cloud-mask on crée un rectangle blanc presque identique à la barre verticale de la flèche, mais qui descend 4px plus bas, et sans bordure.

8081828384858687
.cloud-mask {
	left: 0;
	right: 0;
	top: 0;
	bottom: -4px;
	border-radius: 1px;
	z-index: 50;
}

Il ne nous reste plus qu’à faire la pointe blanche avec :before et :after, de la même manière que précédemment, mais avec du blanc/transparent à la place du gris/transparent, et en modifiant les dimensions.

088089090091092093094095096097098099100101102103104105106107108109110111112113114115116117118119
.cloud-mask:before, .cloud-mask:after {
	content:'';
	width: 14px;
	height: 13px;
	bottom: -10px;
}
.cloud-mask:before {
	right: -2px;
	border-top-left-radius: 2px;
	-webkit-transform:	skewX(40deg);
	-moz-transform:		skewX(40deg);
	-o-transform:		skewX(40deg);
	transform:		skewX(40deg);
	background: transparent -webkit-gradient(linear, 0 0, 14 14, from(#fff), to(transparent), color-stop(0.5, #fff), color-stop(0.5, transparent));
	background: transparent -webkit-linear-gradient(-45deg, #fff 50%, transparent 50%);
	background: transparent    -moz-linear-gradient(-45deg, #fff 50%, transparent 50%);
	background: transparent      -o-linear-gradient(-45deg, #fff 50%, transparent 50%);
	background: transparent         linear-gradient(-45deg, #fff 50%, transparent 50%);
}
.cloud-mask:after {
	left: -2px;
	border-top-right-radius: 2px;
	-webkit-transform:	skewX(-40deg);
	-moz-transform:		skewX(-40deg);
	-o-transform:		skewX(-40deg);
	transform:		skewX(-40deg);
	background: transparent -webkit-gradient(linear, 14 0, 0 14, from(#fff), to(transparent), color-stop(0.5, #fff), color-stop(0.5, transparent));
	background: transparent -webkit-linear-gradient(-135deg, #fff 50%, transparent 50%);
	background: transparent    -moz-linear-gradient(-135deg, #fff 50%, transparent 50%);
	background: transparent      -o-linear-gradient(-135deg, #fff 50%, transparent 50%);
	background: transparent         linear-gradient(-135deg, #fff 50%, transparent 50%);
}

That’s it!

Ça y est, nous avons achevé notre icône. La méthode n’est pas ce qu’il y a de plus simple, mais c’est celle qui fourni le meilleur résultat parmi celles que j’ai testé. Même une fois zoomé, voilà ce que ça donne :

Icône Cloud CSS - Zoom

Mes 2ème et 3ème méthodes utilisent une div en moins.
La 2ème est même plus compliquée que celle présentée car il faut tenir compte d’un bug de Firefox, qui ne permet pas de faire passer un pseudo-élément :before ou :after sous l’élément le contenant avec z-index. Donc il faut créer d’abord la pointe grise avec .cloud-arrow, puis la barre verticale avec :before, et enfin la pointe blanche avec :after. D’où un amoncèlement de scaleX(), scaleY(), rotate() et translate().
La seule chose intéressante à retenir avec cette 2ème méthode, c’est que lorsque l’on fait un transform à plusieurs « effets », l’ordre de ces « effets » a de l’importance :
transform: rotate(-45deg) scaleX(.91) scaleY(.77); n’aura pas le même résultat que :
transform: scaleX(.91) scaleY(.77) rotate(-45deg);.

La 3ème méthode est beaucoup plus simple puisque j’utilise tout simplement border pour faire les triangles, cependant, le rendu n’est pas terrible. En plus, Opera va poser un petit problème.