Astuces Web - Info-bulles

Présentation

À l'aide de l'attribut title des balises HTML, il est possible d'afficher une info-bulle lorsque la souris survole l'élément.

Exemple
<span title="Voici une info-bulle !">Survolez-moi !</span>

Sympa, non ? Mais, je ne sais pas ce que vous en pensez, mais l'info-bulle est assez laide quand même... En tout cas, elle l'est dans les vieux navigateurs :
oldTooltips

Bah et alors ! Avec un peu de CSS on doit bien pouvoir régler ça, non ?

Ah si seulement (¬_¬";)... le problème, c'est que cette info-bulle ne correspond pas à une balise HTML. Elle est gérée par le navigateur et il n'est donc pas possible de modifier son aspect.
Mais ne vous en faites pas. Il existe plein de façon de remédier à cela. Laissez-moi vous montrer ma façon !

Info-bulles sur mesures

La méthode que je vais vous présenter ici consiste à écrire et utiliser des fonctions JavaScript qui permettront d'afficher le texte que bon nous semble lorsque l'on survole un élément.
Par la suite, nous utiliserons un peu de CSS afin de donner un aspect un peu plus présentable à notre info-bulle.

Faire sa bulle

Pour afficher une info-bulle personnalisée, il existe 2 manières de procéder :
  • utiliser une div prévue à cet effet ;
  • créer une nouvelle div et l'ajouter à la page.

La première méthode consiste à créer dans la page une zone qui sera affichée lorsque l'on survole le bon élément. Cela peut être fait avec du CSS, en jouant avec les états :hover et, du coup, Ça n'a rien de vraiment intéressant.
En toute logique, je vais donc vous présenter la seconde méthode (^_^).

Pour commencer, on va devoir créer une balise en JavaScript :

var div = document.createElement('div');
div.id = 'tooltip';
div.style.visibility = "hidden";
document.body.appendChild(this.div);

On créé la balise, on lui donne un identifiant, on la cache puis on l'ajoute au document.
Ensuite, il faut remplir la balise avec le contenu que l'on souhaite afficher, puis la rendre visible.

div.innerHTML = text;
div.style.visibility = "visible";
isVisible = true;

Avec quelques améliorations et en mettant tout ça dans une fonction, on obtient ceci :

var isVisible = false;
var div = null;

function show(text) {
	if (isVisible == false) {
		if (div == null) {
			// add tooltips to body
			div = document.createElement('div');
			div.id = 'tooltip';
			div.style.visibility = "hidden";
			document.body.appendChild(div);
		}
		
		// Make tooltips visible and fill with the text
		div.innerHTML = text;
		div.style.visibility = "visible";
		isVisible = true;
	}
}

Du coup, il faut maintenant faire disparaitre l'info-bulle. Pour cela, rien de bien extraordinaire :

function hide() {
	if (isVisible == true) {
		// Hide tooltips
		if (div != null) {
			div.style.visibility = "hidden";
		
			// Remove tooltips from body
			document.body.removeChild(div);
			div = null;
		}
		isVisible = false;
	}
}

On vérifie que l'info-bulle est visible et que la balise existe, on la cache puis on la retire de la page.

Bulles à tête chercheuse

Bien. On sait créer notre info-bulle et la détruire, mais il faudrait pouvoir la positionner au bon endroit. D'ailleurs, si l'info-bulle pouvait suivre la souris, ça pourrait être sympa. Et beh y'a plus qu'â :

function move(e) {
	if (isVisible) {
		var div = document.getElementById('tooltip');
		if (navigator.appName != "Microsoft Internet Explorer") {
			div.style.left = e.pageX + 5 + "px";
			div.style.top = e.pageY + 10 + "px";
		} else {
			if (document.documentElement.clientWidth > 0) {
				div.style.left = 20 + e.x
						+ document.documentElement.scrollLeft + "px";
				div.style.top = 10 + e.y
						+ document.documentElement.scrollTop + "px";
			} else {
				div.style.left = 20 + e.x
						+ document.body.scrollLeft + "px";
				div.style.top = 10 + e.y
						+ document.body.scrollTop + "px";
			}
		}
	}
}

Alors ici, ça peut faire un peur mais il ne faut pas ;)
La fonction effectue juste des tests supplémentaire en fonction du navigateur (bizarrement, c'est encore Microchiotte qui nous €$*/&!$...).
Donc, en clair, la fonction va positionner l'info-bulle un peu en dessous de là où se trouve la souris, en se basant sur les coordonnées d'origine de l'évènement.
Pour finir, on indique on document d'appeler la fonction lorsque l'on bouge la souris dans la page :

document.onmousemove = move;

Buller en beauté

Bon, OK. On a notre info-bulle, mais si vous tester tel quel, vous constaterez qu'il manque quelque chose... l'info-bulle !
Et oui. On a pas définit que la position d'une info-bulle devait être absolue pour prendre en compte top et left (si vous regardez en bas de la page, vous pourrez voir apparaître l'info-bulle), et on a même paramétré l'affichage ! Du coup, c'est encore plus laid que ce qu'avec title (¬_¬";)...
Heureusement, le CSS arrive !

Pour empêcher cela, on ajoute la classe de la balise au moment de la création :

div.className = 'tooltips';

Puis on définit une classe CSS correspondant :

.tooltips {
	max-width:500px;
    overflow: hidden;
    position:absolute;
	border:1px solid #C0C0C0;
	background:url('bg_tooltip.gif') 100% 100% repeat-x #FFFFFF;
	
	padding:8px;
    font-family:Consolas, Arial, san-serif !important;
    font-size:11px;
    color:#80808;
}

Bien évidemment, vous êtes libre de modifier l'apparence de votre info-bulle (je vous recommande tout de même de ne pas trop vous éloigner de la première partie du CSS).
Pour le fond, j'utilise une image toute bête qui est un dégradé de blanc vers un gris (très très) pâle. Vous pouvez facilement le reproduire avec du CSS3 :

.tooltips {
	background-image: -o-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -moz-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -webkit-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -ms-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -webkit-gradient(linear, left top, left bottom, 
		color-stop(0, rgb(255, 255, 255) ),
		color-stop(1, rgb(240, 240, 240) ) );
	background-image: linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
}

Et pour rendre le tout encore plus agréable, on met des bords arrondis.

.tooltips {
	-webkit-border-radius: 6px;
	-moz-border-radius : 6px;
	border-radius : 6px;
}

Code complet

JavaScript

var isVisible = false;
var div = null;

function show(text) {
	if (isVisible == false) {
		if (div == null) {
			// add tooltips to body
			div = document.createElement('div');
			div.id = 'tooltip';
			div.className = 'tooltips';
			div.style.visibility = "hidden";
			document.body.appendChild(div);
		}
		
		// Make tooltips visible and fill with the text
		div.innerHTML = text;
		div.style.visibility = "visible";
		isVisible = true;
	}
}

function hide() {
	if (isVisible == true) {
		// Hide tooltips
		if (div != null) {
			div.style.visibility = "hidden";
		
			// Remove tooltips from body
			document.body.removeChild(div);
			div = null;
		}
		isVisible = false;
	}
}

function move(e) {
	if (isVisible) {
		var div = document.getElementById('tooltip');
		if (navigator.appName != "Microsoft Internet Explorer") {
			div.style.top = e.pageY + 10 + "px";
			div.style.left = e.pageX + 5 + "px";
		} else {
			if (document.documentElement.clientWidth > 0) {
				div.style.top = 10 + e.y
						+ document.documentElement.scrollTop + "px";
				div.style.left = 20 + e.x
						+ document.documentElement.scrollLeft + "px";
			} else {
				div.style.top = 10 + e.y
						+ document.body.scrollTop + "px";
				div.style.left = 20 + e.x
						+ document.body.scrollLeft + "px";
			}
		}
	}
}
document.onmousemove = move;

CSS

.tooltips {
	max-width:500px;
    overflow: hidden;
    position:absolute;
	border:1px solid #C0C0C0;
	background:url('bg_tooltip.gif') 100% 100% repeat-x #FFFFFF;
	
	padding:8px;
    font-family:Consolas, Arial, san-serif !important;
    font-size:11px;
    color:#80808;
}

CSS3

.tooltips {
	-webkit-border-radius: 6px;
	-moz-border-radius : 6px;
	border-radius : 6px;
	
	background-image: -o-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -moz-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -webkit-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -ms-linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
	background-image: -webkit-gradient(linear, left top, left bottom, 
		color-stop(0, rgb(255, 255, 255) ),
		color-stop(1, rgb(240, 240, 240) ) );
	background-image: linear-gradient(top, rgb(255, 255, 255) 0%,
		rgb(240, 240, 240) 100% );
}

Résultat

Utilisation

	Survolez-moi !

Une démonstration brute est disponible ici.

Pour aller plus loin

Info-bulle savoyarde

Pour avoir encore plus de confort, il est fréquent de voir apparaitre les info-bulles avec un fondu. Pour cela, on utilise la bibliothèque jQuery et sa fonction fadeIn() :

$('tooltip').css({top: e.pageY+10,left: e.pageX+20}).fadeIn(350);

Encore mieux ?

Du coup, c'est un peu bête car on n'utilise plus l'attribut title et on est obligé de définir une classe, l'action quand la souris rentre et quand elle sort de l'élément à chaque fois...
Une amélioration classique de ce genre de système est de continuer d'utiliser title et d'avoir une fonction qui va parser la page et faire la transition vers le système présenté jusqu'ici.
Avec jQuery, voilà ce que cela pourrait donner :

$('body [title]').each(function() {
	var $item = $(this);
	var $tooltip;
	
	// Make sure the item has a title
	if( $item.attr('title').length>0 ) {
		var title = this.title;

		// Empty the title
		this.title = '';
		
		// Actions to be taken when hovering
		$item.hover(function(e) {
			
			// Build the tooltip and append it to the body
			$tooltip = $('
') .appendTo('body') .hide(); // Append the content to the tooltip $tooltip.html(title); // Set the tooltip position and fade it in $tooltip.css({ top: e.pageY+10, left: e.pageX+20 }) .fadeIn(350); }, function() { // Remove the tooltip $tooltip.remove(); }); // Bind a mouse move function $item.mousemove(function(e) { // Move the tooltip relative to the mouse $tooltip.css({ top: e.pageY+10, left: e.pageX+20 }); }); } });

La démonstration jQuery est disponible ici.

Vous pouvez également télécharger une archive de ma version optimisée ici.

À propos

Ce petit tutoriel a été réalisé en se basant sur mes connaissances personnelles et mon vécu. Je ne prétends pas montrer ici LA solution mais mon approche pour résoudre un «problème» donné.

Les extraits de code sont inclus et mis en forme dans la page à l'aide de Syntax Highlighter. C'est une extension entièrement écrite en JavaScript. Jetez-y un œil ou deux ;)

Vous l'aurez peut-être remarqué, mais toutes les balises textes que j'ai utilisé et qui avait une info-bulle était soulignées en pointillé. Ce n'est pas le fait du navigateur !
C'est une «règle» typographique que l'on retrouve fréquemment dans les sites Web pour indiquer la présence d'informations supplémentaire.

abbr, acronym, span[title], strong[title], em[title], label[title], .info {
	border-bottom:1px dotted #666; /* souligner en pointillé */
	cursor: help; /* changer le curseur de la souris */
}

Pour voir une autre méthode pour modifier les info-bulles, vous pouvez aller ici.

Back to top