Aujourd’hui nous allons créer des tooltips en CSS.
Au programme, réaliser des triangles en CSS2, des coins arrondis en CSS3, des ombres en CSS2 et 3, des fonds dégradés en CSS3, des transitions CSS3 et l’utilisation des pseudo-éléments « :before » et « :after ».
But
Le but de ce tutoriel n’est pas vraiment de créer des tooltips utilisables en production (même s’ils fonctionnent, ils requièrent un marquage HTML supplémentaire et un autre détail va nous gêner si nous voulons utiliser les transitions CSS), mais plutôt d’apprendre à utiliser certaines propriétés CSS. En effet, d’autres techniques seraient plus adaptées (comme d’utiliser l’attribut « title » du lien avec le pseudo-élément « :after ». Cependant avec ce tutoriel, le rendu esthétique sera amélioré ;)
Faire un triangle en CSS
Faire un triangle en CSS n’est pas compliqué, il suffisait juste de trouver l’astuce. En plus, nous allons utiliser une seule balise HTML et une propriété CSS bien connue : border.
Prenons par exemple une balise <span>
vide et voyons comment utiliser le CSS pour transformer un rectangle en triangle :
display: block; width: 20px; height: 20px; border: #3F342A solid 10px; |
display: block; width: 0; height: 0; border: #3F342A solid 10px; |
display: block; width: 0; height: 0; border: transparent solid 10px; border-top-color: #3F342A; |
Nous utiliserons cette astuce pour faire la pointe sous les tooltips.
Marquage HTML
1
<a class="hastip" href="#">Hover me<span class="tip red">Rouge!</span></a>
Nous rajoutons juste la classe « hastip » aux liens qui bénéficieront d’un tooltip, ainsi qu’une balise <span>
qui contiendra le texte de votre tooltip. La classe « tip » servira seulement à ne pas appliquer les CSS à des <span>
qui se trouveraient à l’intérieur du lien. La classe « red » servira à choisir la couleur du tooltip.
CSS
Le lien :
1234
a.hastip {
position: relative;
text-decoration: none;
}
Le tooltip : mise en boite, positionnement et mise en forme du texte. Nous positionnons en absolu le tooltip qui fera 40px de haut (avec une seule ligne de texte).
0506070809101112131415161718
.tip {
position: absolute;
left: 0;
top: -30px;
z-index: 30; /* A modifier selon les besoins */
padding: 0 20px;
width: auto;
height: 40px;
line-height: 40px;
font-size: 18px;
font-weight: bold;
color: #191919;
white-space: nowrap; /* Pour garder tout le texte sur 1 seule ligne */
}
Le tooltip : bordures de 3 pixels et arrondis de 6 pixels.
19202122232425
.tip {
border: solid 3px #191919;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
-o-border-radius: 6px;
border-radius: 6px;
}
Le tooltip : ombres. On rajoute du volume au texte avec 1 pixel noir (60% d’opacité) au-dessus et 1 pixel blanc au-dessous. De la même façon, nous rajoutons du volume au tooltip avec 1 pixel blanc (70% d’opacité) au-dessus (avec inset). Puis nous rajoutons une ombre autour du tooltip, décalée de 4 pixels vers le bas et un flou de 16 pixels.
26272829303132
.tip {
text-shadow: 0 -1px 1px rgba(0,0,0,.6), 0 1px 1px rgba(255,255,255,1);
-webkit-box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
-moz-box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
-o-box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
}
Le tooltip : le fond. Nous allons mettre une couleur de fond par défaut (blanc à 50% d’opacité) et rajouter un dégradé (noir, 27% d’opacité en haut et stoppé à 30% de la hauteur, vers 0% d’opacité en bas).
3334353637383940
.tip {
background-color: rgba(255,255,255,.5);
background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,.27)), to(rgba(0,0,0,0)), color-stop(0.3, rgba(0,0,0,.27)));
background-image: -webkit-linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
background-image: -moz-linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
background-image: -o-linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
background-image: linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
}
Le tooltip : transition CSS. Nous allons jouer sur l’opacité du tooltip et sa hauteur. Habituellement, le tooltip est par défaut dissimulé grâce à la propriété display: none; puis affiché avec display: block; au survol de la souris. Malheureusement, les effets désirés ne vont pas fonctionner si nous utilisons la propriété display, les transitions CSS seront bloquées. Il faudra donc nous passer de la propriété display hélas, et jouer sur l’opacité. Ce qui est le petit défaut de la méthode, car le tooltip, même invisible, reste « survolable » avec la souris.
N’oubliez pas que ces transitions CSS seront visibles seulement avec Firefox 4, Safari et Chrome. Pour Opera c’est pour bientôt je crois. Quand à IE… ***Je pouffe***
[update] Rajout de transform: scale(0);
afin de réellement masquer le tooltip. Pour plus d’explications sur la transition CSS, voir le paragraphe suivant : survol.
404142434445464748495051
.tip {
opacity: 0;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); /* Fucking IE */
-webkit-transform: scale(0);
-moz-transform: scale(0);
-o-transform: scale(0);
transform: scale(0);
-webkit-transition: opacity .3s ease-in-out, top .3s ease-in-out, -webkit-transform 0s linear .4s;
-moz-transition: opacity .3s ease-in-out, top .3s ease-in-out, -moz-transform 0s linear .4s;
-o-transition: opacity .3s ease-in-out, top .3s ease-in-out, -o-transform 0s linear .4s;
transition: opacity .3s ease-in-out, top .3s ease-in-out, transform 0s linear .4s;
}
[update] Le tooltip : survol. Nous devons maintenant afficher le tooltip au survol de la souris. Comme prévu, nous allons mettre l’opacité à 1, faire monter le tooltip de 20px, mettre le scale() à 1, et animer tout ça avec des transitions CSS.
4546474849505152535455565758
.hastip:hover .tip, .hastip:active .tip {
opacity: 1;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100); /* Fucking IE */
top: -60px;
z-index: 40;
-webkit-transform: scale(1);
-moz-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
-webkit-transition: opacity .3s ease-in-out, top .3s ease-in-out;
-moz-transition: opacity .3s ease-in-out, top .3s ease-in-out;
-o-transition: opacity .3s ease-in-out, top .3s ease-in-out;
transition: opacity .3s ease-in-out, top .3s ease-in-out;
}
Vous remarquez que nous utilisons une deuxième fois une transition CSS et qu’il y a une différence entre les deux. En fait, la précédente va servir pour masquer le tooltip, alors que celle-ci sert pour le montrer.
Avec cette transition sur le :hover (pour montrer le tooltip) : nous animons uniquement opacity et top, mais pas scale(). Ainsi le tooltip apparait directement à la bonne taille et les animations sur opacity et top peuvent se dérouler.
Avec la transition sur l’état « normal » (pour masquer le tooltip) : nous animons également scale(), sinon scale() va passer directement à 0 dès que la souris quitte le lien, l’animation sur opacity et top ne se verrais alors pas. Pour cela, nous utilisons un retard : transform 0s linear .4s
. transform
correspond donc à scale(), qui va passer de 1 à 0. 0s
est la durée de la transition : 0 secondes car on ne veut pas la voir dans notre cas, donc autant la mettre à zéro pour ne pas faire dépenser des ressources inutiles à l’ordinateur du visiteur. linear
est la courbe de la transition, on met ce qu’on veut, de toute façon on ne verra pas l’animation sur scale(). 0.4s
est le délais avant le début de l’animation. La durée des transitions sur opacity et top étant de 0.3s, celle sur scale() débutera une fois que le tooltip sera entièrement masqué.
Ce qui donne au final pour le tooltip :
050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
.tip {
opacity: 0;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0); /* Fucking IE */
position: absolute;
left: 0;
top: -30px;
z-index: 30;
padding: 0 20px;
height: 40px;
width: auto;
border: solid 3px #191919;
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
-o-border-radius: 6px;
border-radius: 6px;
line-height: 40px;
font-size: 18px;
font-weight: bold;
color: #191919;
white-space: nowrap;
text-shadow: 0 -1px 1px rgba(0,0,0,.6), 0 1px 1px rgba(255,255,255,1);
background-color: rgba(255,255,255,.5);
background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0,0,0,.27)), to(rgba(0,0,0,0)), color-stop(0.3, rgba(0,0,0,.27)));
background-image: -webkit-linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
background-image: -moz-linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
background-image: -o-linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
background-image: linear-gradient(top, rgba(0,0,0,.27) 30%, rgba(0,0,0,0));
-webkit-box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
-moz-box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
-o-box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
box-shadow: inset 0 1px 1px rgba(255,255,255,.7), 0 4px 16px #191919;
-webkit-transform: scale(0);
-moz-transform: scale(0);
-o-transform: scale(0);
transform: scale(0);
-webkit-transition: opacity .3s ease-in-out,top .3s ease-in-out,-webkit-transform 0s linear .4s;
-moz-transition: opacity .3s ease-in-out,top .3s ease-in-out,-moz-transform 0s linear .4s;
-o-transition: opacity .3s ease-in-out,top .3s ease-in-out,-o-transform 0s linear .4s;
transition: opacity .3s ease-in-out,top .3s ease-in-out,transform 0s linear .4s;
}
.hastip:hover .tip, .hastip:active .tip {
opacity: 1;
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=100); /* Fucking IE */
top: -60px;
z-index: 40;
-webkit-transform: scale(1);
-moz-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
-webkit-transition: opacity .3s ease-in-out, top .3s ease-in-out;
-moz-transition: opacity .3s ease-in-out, top .3s ease-in-out;
-o-transition: opacity .3s ease-in-out, top .3s ease-in-out;
transition: opacity .3s ease-in-out, top .3s ease-in-out;
}
Maintenant, utilisons des triangles afin de créer la pointe sous le tooltip. Pour celà, il nous faudra deux triangles : un pour simuler la bordure, l’autre pour la pointe elle-même. Les pseudo-éléments :before et :after vont nous servir. Avec :before nous créons la bordure, et avec :after nous créons la pointe (car :after passera au-dessus de :before).
59606162636465666768697071727374757677
.tip:before, .tip:after {
content: '';
display: block;
position: absolute;
left: 20px;
width: 0;
height: 0;
}
.tip:before {
border: solid 15px transparent;
border-top-color: #191919;
margin-left: -15px;
bottom: -31px;
}
.tip:after {
border: solid 12px transparent;
margin-left: -12px;
bottom: -24px;
}
La touche finale : la couleur
Au point où nous en sommes, nos tooltips sont transparents, avec bordure, ombres, et texte. Il ne reste plus qu’à rajouter la couleur aux tooltips et aux pointes. Cette couleur sera modifiable selon la classe attribuée au tooltip.
7879808182838485868788
.red {
text-shadow: 0 -1px 1px #600, 0 1px 1px #f00;
background-color: #b00;
-webkit-box-shadow: inset 0 1px 1px #d00, 0 4px 16px #191919;
-moz-box-shadow: inset 0 1px 1px #d00, 0 4px 16px #191919;
-o-box-shadow: inset 0 1px 1px #d00, 0 4px 16px #191919;
box-shadow: inset 0 1px 1px #d00, 0 4px 16px #191919;
}
.red:after {
border-top-color: #b00;
}
Allez, tant que nous y sommes, rajoutons d’autres couleurs :)
089090091092093094095096097098099100101102103104105106107108109110111112113114115116117118119120121
.green {
text-shadow: 0 -1px 1px #060, 0 1px 1px #0f0;
background-color: #0b0;
-webkit-box-shadow: inset 0 1px 1px #0d0, 0 4px 16px #191919;
-moz-box-shadow: inset 0 1px 1px #0d0, 0 4px 16px #191919;
-o-box-shadow: inset 0 1px 1px #0d0, 0 4px 16px #191919;
box-shadow: inset 0 1px 1px #0d0, 0 4px 16px #191919;
}
.green:after {
border-top-color: #0b0;
}
.blue {
text-shadow: 0 -1px 1px #066, 0 1px 1px #0ff;
background-color: #0cf;
-webkit-box-shadow: inset 0 1px 1px #0dd, 0 4px 16px #191919;
-moz-box-shadow: inset 0 1px 1px #0dd, 0 4px 16px #191919;
-o-box-shadow: inset 0 1px 1px #0dd, 0 4px 16px #191919;
box-shadow: inset 0 1px 1px #0dd, 0 4px 16px #191919;
}
.blue:after {
border-top-color: #0cf;
}
.grey {
text-shadow: 0 -1px 1px #666, 0 1px 1px #fff;
background-color: #bbb;
-webkit-box-shadow: inset 0 1px 1px #ddd, 0 4px 16px #191919;
-moz-box-shadow: inset 0 1px 1px #ddd, 0 4px 16px #191919;
-o-box-shadow: inset 0 1px 1px #ddd, 0 4px 16px #191919;
box-shadow: inset 0 1px 1px #ddd, 0 4px 16px #191919;
}
.grey:after {
border-top-color: #bbb;
}
Bien, dites moi ce que vous pensez de tout ça dans les commentaires.
[update] Article originalement publié le 29 janvier 2011.
Commentaires
Commentaire de L'ébahi.
Excellent tutoriel. Ce site mérite d’être beaucoup plus connu!
Commentaire de Elfie.
Toute nouvelle dans le web, je suis ravie de tomber sur des blogs comme le tien !
Un grand merci pour cette démonstration de CSS 3 ! Faut que je potasse mes pseudo éléments, je vois que tu t’en sers beaucoup et que ca semble bien utile !
Commentaire de Greg.
Salut Elfie.
En effet j’utilise beaucoup les pseudo-éléments et les pseudo-classes ici, beaucoup moins en production car il faut hélas garder un minimum de compatibilité avec Celui-Dont-On-Ne-Doit-Pas-Prononcer-Le-Nom :(
Enfin, il faut trouver un juste milieu pour une dégradation convenable.
Commentaire de tguyfr.
Je rêve d’un plugin de ce genre pour annoter les devoirs de mes élèves sur mon WP. On surligne, on clique sur un bouton, on commente ou on corrige et au suivant… Ah oui, avec une capacité multi users (couleurs paramétrables) et un panneau d’admin où modérer les commentaires…