miércoles, 6 de marzo de 2013

Tutorial: como hacer tooltips con CSS

Un tooltip es esa ventanita de información que aparece cuando colocamos el ratón sobre algún elemento, como podemos ver en esta imagen de un botón de Gmail:


Se puede implementar de muchas maneras, aquí vamos a ver las 2 opciones más sencillas: con HTML y con CSS. Dejaremos para otra entrada la implementación con JavaScript.

HTML, tooltips básicos con el atributo title


En HTML el atributo title puede utilizarse para mostrar un tooltip básico. Es válido para casi todos los elementos ( en HTML5 ya se puede incluir en todos ):
<button title="This is a tooltip" type="button">Press</button>
El problema es que no admite ningún tipo de personalización. Sólo puede mostrarse texto simple, no podemos formatearlo mediante etiquetas HTML ni poner saltos de línea donde queramos.

Elementos de un tooltip

Los conceptos para crear un tooltip propio son sencillos, básicamente el mensaje no es más que un elemento HTML, normalmente un span o un div, con un texto informativo dentro.

<div class="tooltip">
This is a tooltip
</div>
Despues, mediante estilos CSS, le damos el aspecto que queramos y lo posicionamos donde corresponda con posicionamiento absoluto para que no desplace a otros elementos de la página al mostrarse:

.tooltip {
  position: absolute;
  padding: 10px;
  background-color: gray;
  color: white;
  top: 100%;
  left: 95%;
}

Jugando con los estilos podemos crear ejemplos espectaculares como estos, sacados del post [CSS3 tooltips de Catalin Rosu] (http://www.red-team-design.com/css3-tooltips):


Tooltips usando sólo CSS. El método tradicional

Para crear el mensaje utilizando sólo CSS vamos a incluir el texto de información en un span que inicialmente estará oculto ( display: none). Para que se muestre cuando colocamos el ratón encima (hover) definiremos un estilo diferente para la pseudo-clase :hover con display: block.
<button>Press
    <span class="tooltip">This is a tooltip</span>
</button>
El siguiente paso es definir el CSS para darle el aspecto que queramos, colocarlo en el lugar donde debe mostrarse y definirlo como oculto por defecto y visible sólo en el :hover .
button {
  position: relative;
}

.tooltip {
  position: absolute;
  display: none;
  border: 1px solid black;
  padding: 3px;
  background-color: gray;
  color: white;
  width: 100px;
  left: 100%;
  top: 100%;
}

button:hover .tooltip {
    display:block;
}

Nos quedaría:



Para que el mensaje aparezca siempre en la esquina inferior izquierda del elemento, hemos definido la posición como:

position: absolute;
top: 100%;
left: 100%;

El problema de este método es que el HTML queda confuso y poco semántico porque el span del mensaje se incluye dentro del elemento. Si queremos ponerlo fuera tenemos que "envolverlos" en un div o span extra de forma que sea este elemento el que muestra el tooltip al hacer hover con el ratón y nos sirva como marco para que aparezca posicionado con respecto al elemento.

//HTML
<div class="tooltipWrapper">
<button>Press</button>
<span class="tooltip">This is a tooltip</span>
</div>
//CSS

.tooltipWrapper {
  display: inline-block;
  position: relative;
}

.tooltip {
  position: absolute;
  display: none;
  border: 1px solid black;
  padding: 5px;
  background-color: gray;
  color: white;
  width: 100px;
  left: 50%;
  top: 100%;
}

.tooltipWrapper:hover .tooltip {
    display:block;
}

El display: inline-block se pone para que el div se ajuste al tamaño del contenido. Si no lo ponemos tendría todo el ancho del navegador. En la siguiente imagen se puede ver cómo quedaría. El div.tooltipWrapper está marcado con un borde rojo para verlo:



En esta ocasión hemos puesto left: 50% para que aparezca más centrado.
Si queremos mostrar el mensaje sobre una imagen necesitamos este div envolvente ( wrapper ) porque la etiqueta <img> no encierra contenido:

<div class="tooltipWrapper">
<img src="myImage.jpg" />
    <span class=".tooltip">This is a tooltip</span>
</div>
Con el mismo CSS del ejemplo anterior obtenemos:



Jugando con los estilos podemos darle el aspecto que queramos, incluso incluir transiciones o animaciones para para que se muestre más lentamente o vaya variando la opacidad ( en los navegadores que lo soporten ). En el siguiente ejemplo utilizamos el pseudo elemento :before para crear el pequeño triángulo que apunta al elemento y hacerlo similar al de Google que mostramos en la primera imagen:
//HTML
This is a tooltip
//CSS .tooltipWrapper { display: inline-block; position: relative; } .tooltip { position: absolute; display: none; border: 1px solid black; padding: 5px; background-color: gray; color: white; width: 100px; left: -50%; bottom: -37px; } .tooltip:before{ content: ' '; display: block; position: absolute; left: 45px; top: -8px; width: 14px; height: 14px; border-color: black; border-width: 1px; border-style: solid none none solid; background-color: gray; transform: rotate(45deg); -webkit-transform: rotate(45deg); -ms-transform: rotate(45deg); -moz-transform: rotate(45deg); } .tooltipWrapper:hover .tooltip { display:block; }
El resultado es:


Limitaciones del método tradicional

Como hemos visto no es muy semántico porque tenemos un elemento extraño dentro del contenido del botón (el span) o un elemento extra que envuelva el elemento y el tooltip. Podemos solucionarlo utilizando CSS3 para coger el valor de un atributo HTML y colocarlo como contenido de un elemento.

Tooltips con CSS3 utilizando un atributo de HTML para el contenido

Este método es mucho más semántico porque no necesitamos el span para el contenido del tooltip ni el div extra que lo envuelve. Utilizamos un atributo personalizado de HTML del tipo data- para el mensaje y el pseudo-elemento ::before para construir el tooltip:
//HTML
<button class="tooltip2" data-tooltip="this is the tooltip!">
    Press
</button>    

//CSS
.tooltip2 {
  position: relative;
}

.tooltip2::before {
    position:absolute;
    display: none;
    content: attr(data-tooltip) ;
    border: 1px solid black;
    padding: 3px;
    background-color:gray;
    color: white;
    white-space:nowrap;
    left: 50%;
    top: 100%;
 }

.tooltip2:hover::before {
    display: block;

 }




El texto del tooltip se coge del atributo data-tooltip mediante la línea CSS3:
content: attr(data-tooltip) ;
Podriamos utilizar title como vimos al principio, pero aparecería nuestro mensaje y el del navegador al mismo tiempo.
Recordemos que tenemos aún un pseudo-elemento extra disponible ( ::after ) por si queremos añadir también el pequeño triángulo que apunta al elemento.

El inconveniente de tener el texto en el atributo es que deben ser textos sencillos. No podemos crear textos complicados  con formato o imágenes.

Fuentes:
W3 Org title definiton
Simple cross-browser tooltip with CSS
Tooltips courtesy of HTML5 data attributes