Advertisement
  1. Web Design
  2. CSS

Cómo Hacer Descripciones Emergentes Mágicas y Animadas Con CSS

Scroll to top
Read Time: 13 min

() translation by (you can also view the original English article)

Las descripciones emergentes son una gran forma de mejorar una UI cuando tus usuarios necesitan contexto extra para ese elegante icono, o cuando quieren alguna seguridad para dar clic a un botón, o tal vez un subtitulo secreto para acompañar una imagen. Hagamos algunas descripciones emergentes animadas, justo ahora, con nada más que HTML y CSS.

Demostración

Aquí está hacia lo que estaremos trabajando:

Antes de sumergirte en la caldera, echemos un vistazo a lo que estaremos fabricando. La meta principal es tener una manera simple de agregar una descripción emergente, así que haremos eso usando un atributo tooltip personalizado:

1
<span tooltip="message">visible text or icon, etc.</span>

Un Nota Sobre Accesibilidad y Capacidad

Si estás buscando 508-complacientes descripciones emergentes, o necesitas descripciones emergentes más inteligentes con detección de colisión con contenedor y/o soporte para contenido HTML vs. texto plano, hay muchas soluciones que usan scripts de terceros para satisfacer esas necesidades por ti.

"JavaScript es imperativo para hacer componentes interactivos totalmente accesibles." -- Sara Soueidan, Construir descripciones emergentes de ayuda completamente accesibles...es más difícil de lo que pensé

Este tutorial no aborda específicamente necesidades de accesibilidad. Conoces a tus usuarios y lo que necesitan, así que asegúrate de considerar sus necesidades en este respecto también.

Establezcamos Algunas Expectativas

  • No se requiere JavaScript
  • Estaremos usando selectores de atributos (no nombres de clases), con el emparejamiento de patrón integrado de CSS
  • Agregar elementos DOM existentes (no se requieren nuevos elementos en tu marcado*)
  • Los ejemplos de código son libres de prefijos (agrega prefijos propietarios para tus navegadores meta si es necesario)
  • Asume paso del ratón/flotar para disparar las descripciones emergentes
  • Solo descripciones emergentes de texto plano (HTML, imágenes, etc. no están soportadas)
  • Animaciones sutiles mientras se invocan las descripciones emergentes

¡Muy bien! ¡Vamos a Rockear Este Barco!

Oh, espera. Tenemos un asterisco con el cuál lidiar primero, sobre "no necesitar ninguna marcado extra". Esto es mágico, después de todo. Nuestras descripciones emergentes realmente no necesitan ningunos elementos DOM extra ya que están hechos completamente de pseudo-elementos (las cosas ::before y ::after) que podemos controlar via CSS.

Si ya estás utilizando los pseudo-elementos de un elemento de otro conjunto de estilos y quieres una descripción emergente sobre ese elemento, entonces podrías necesitar reestructurar un poco.

¡No Hay Fiesta Como Una Fiesta de Descripción Emergente!

Espera. ¡Gremlins! Una advertencia más: posicionamiento CSS. Para que las descripciones emergentes funcionen apropiadamente, su elemento padre (la cosa a la que estamos adjuntando la descripción emergente) necesita ser

  • position: relative, o
  • position: absolute, o
  • position: fixed

Básicamente, cualquiera menos position: static --ese es el modo de posición por defecto asignado a prácticamente todos los elementos por el navegador. Las descripciones emergentes son posicionadas de manera absoluta así que necesitan conocer los límites en los cuáles su absolutes tiene significado. La directiva de posición por defecto static no declara sus propios límites y no dará a nuestras descripciones emergentes un contexto contra los cuales empujar, así que las descripciones emergentes usarán el siguiente elemento parental más cercano que tiene un límite declarado.

Necesitarás decidir cual directiva de posición funciona mejor con cómo estás usando las descripciones emergentes. Este tutorial asume position: relative para el elemento padre. Si tu UI depende en un elemento absolutamente posicionado, entonces alguna reestructura (marcado extra) podría ser necesaria para desplegar una descripción emergente sobre ese elemento.

Vayamos a ver qué pasa.

Selectores de Atributo; Un Recordatorio Rápido

La mayoría de reglas CSS están escritas con nombres de clases en mente, como .esta-cosa, pero CSS tiene un puñado de tipos de selectores. Nuestras descripciones emergentes mágicas van a usar selectores de atributo--esa es la notación de corchetes cuadrados:

1
[foo] {
2
    background: rgba(0, 0, 0, 0.8);
3
    color: #fff;
4
}

Cuando el navegador encuentra algo como esto:

1
<span foo>Check it out!</span>

sabrá que necesita aplicar las reglas [foo] porque la etiqueta <span> tiene un atributo llamado foo. En este caso, el span mismo tendría un fondo negro traslúcido con texto blanco.

Los elementos HTML tienen varios atributos integrados, pero también podemos hacer los propios. Como foo, o tooltip. Por defecto, HTML no sabe que significan estos, pero con CSS podemos decirle a HTML lo que esto significa.

¿Por Qué Selectores de Atributo?

Usaremos primariamente selectores de atributo para una separación de asuntos. Usar atributos sobre nombres de clase no nos da ningún punto extra en la guerra de la especificidad; las clases y atributos tienen la misma especificidad. Sin embargo, usando atributos podemos mantener nuestro contenido con el contenido ya que los atributos HTML pueden tener valores, mientras que las clases no.

Considera el nombre de clase .tooltip vs. el atributo [tooltip] en este código de ejemplo. El nombre de clase es uno de los valores para el atributo [class] mientras que el atributo tooltip tiene un valor, que es el texto que queremos mostrar.

1
<span class="tooltip another-classname">lorem ipsum</span>
2
3
<span tooltip="sit dolar amet">lorem ipsum</span>

Ahora Entrando a la Alquimia de las Descripciones Emergentes

Nuestras ventanas emergentes tienen dos atributos diferentes:

  • tooltip: esto contiene el contenido de la descripción emergente (una cadena de texto plano)
  • flow: opcional; esto nos permite controlar cómo exponer la descripción emergente. Hay muchas colocaciones que podríamos soportar pero cubriremos cuatro colocaciones comunes:
    arriba, izquierda, derecha, abajo.

Ahora, preparemos el trabajo para todas las descripciones emergentes. Las reglas de los pasos 1-5 aplican para todas las descripciones emergentes sin importar qué flow les demos. Los pasos 6-7 tienen distinciones entre los diferentes valores de flow.

1. Relatividad

Esto es para el elemento padre de la descripción emergente. Asignemos una directiva de posición para que el posicionamiento absoluto de las partes de la descripción emergente (los pseudo-elementos ::before y ::after) sean posicionados en contexto para este elemento padre y no en contexto de la página completa o un elemento abuelo o algún otro elemento externo en el árbol DOM.

1
[tooltip] {
2
  position: relative;
3
}

2. Hora Estelar del Pseudo-elemento

Es la hora estelar de los pseudo-elementos. Aquí estableceremos propiedades comunes para las piezas ::before y ::after. La propiedad content es lo que hace que el pseudo-elemento funcione, pero llegaremos ahí pronto.

1
[tooltip]::before,
2
[tooltip]::after {
3
    line-height: 1;
4
    user-select: none;
5
    pointer-events: none;
6
    position: absolute;
7
    display: none;
8
    opacity: 0;
9
10
    /* opinions */
11
    text-transform: none; 
12
    font-size: .9em;
13
}

3. El Tonto

No sé porque "tonto" tiene sentido, pero siempre lo he llamado así. Esta es la pequeña parte triangular puntiaguda que da a las descripciones emergentes su sentir de burbuja de texto apuntando a la cosa de la cuál fueron invocadas. Nota que estamos usando transparent para el color de borde; agregaremos el color después ya que cómo lo agreguemos depende del flow de la descripción emergente.

1
[tooltip]::before {
2
    content: '';
3
    z-index: 1001;
4
    border: 5px solid transparent;
5
}

No es un error de dedo que la declaración content: ' '; tenga una cadena vacía por valor. No queremos nada ahí, pero necesitamos esa propiedad para que exista el pseudo-elemento.

Para hacer un triángulo estamos definiendo un borde sólido con algo de grosor sobre una caja vacía (sin contenido) sin ancho y sin altura, y solo dándole a un lado de la caja color de borde. Para más detalles revisa el siguiente tutorial:

4. ¡Burbujas!

Aquí está la carne de la cosa. Nota la parte content: attr(tooltip) diciendo, "Este pseudo-elemento debería usar el valor del atributo tooltip como su contenido." ¡Por esto usar atributos sobre clases de nombres es tan grandioso!

1
[tooltip]::after {
2
    content: attr(tooltip); /* magic! */
3
    z-index: 1000;
4
    
5
    /* most of the rest of this is opinion */
6
    font-family: Helvetica, sans-serif;
7
    text-align: center;
8
    
9
    /* 

10
    Let the content set the size of the tooltips 

11
    but this will also keep them from being obnoxious

12
    */
13
    min-width: 3em;
14
    max-width: 21em;
15
    white-space: nowrap;
16
    overflow: hidden;
17
    text-overflow: ellipsis;
18
    
19
    /* visible design of the tooltip bubbles */
20
    padding: 1ch 1.5ch;
21
    border-radius: .3ch;
22
    box-shadow: 0 1em 2em -.5em rgba(0, 0, 0, 0.35);
23
    background: #333;
24
    color: #fff;
25
}

Nota los valores z-index para el tonto y la burbuja. Estos son valores arbitrarios, pero ten en mente que un valor z-index es relativo. Significado: un valor z-index de 1001 dentro de un elemento con z-index de 3 solo significa que el elemento 1001 será el elemento de más arriba dentro del contenedor con z-index de 3.

El z-index de la burbuja debería ser al menos un paso más abajo del z-index del tonto. Si es el mismo o más alto que el del tonto, puedes terminar con un efecto de color inconsistente sobre el tonto si tus descripciones emergentes emplean un box-shadow.

Para un vistazo más detallado de la propiedad z-index, mira el siguiente tutorial:

5. Acción de Interacción

Nuestras descripciones emergentes son activadas pasando el ratón sobre el elemento con la descripción emergente...Casi.

1
[tooltip]:hover::before,
2
[tooltip]:hover::after {
3
    display: block;
4
}

Si vuelves a ver nuestro bloque de estilo en el Paso 2, deberías ver que usamos opacity: 0; junto con display: none; para las partes de nuestra descripción emergente. Hicimos esto de manera que podamos usar efectos de animación CSS cuando las descripciones emergentes de muestren y oculten.

La propiedad display no puede ser animada, ¡pero opacity si! Lidiaremos con las animaciones al final. Si no te interesan las descripciones emergentes animadas, solo borra la declaración opacity: 0; del Paso 2 e ignora la animación en el Paso 7.

La última cosa que necesitaremos que aún aplica a todas la descripciones emergentes es una manera de suprimir una descripción emergente si no tiene contenido. Si estás poblando tus descripciones emergentes con algún sistema dinámico (Vue.js, Angular, React, PHP, etc.) ¡no queremos burbujas vacías!

1
/* don't show empty tooltips */
2
[tooltip='']::before,
3
[tooltip='']::after {
4
    display: none !important;
5
}

6. Control de Flujo

Esta paso se puede volver complicado ya que usaremos algunos selectores no tan comunes para ayudar a nuestras descripciones emergentes a lidiar con sus emplazamientos basado en sus valores flow (o falta de).

"Cosas extrañas están en marcha en el Círculo-K" --- Ted Theodore Logan

Antes de saltar a los estilos, echemos un vistazo a algunos patrones de selector que estaremos usando.

1
[tooltip]:not([flow])::before,
2
[tooltip][flow^="up"]::before {
3
    /* ...

4
    properties: values

5
    ... */
6
}

Esto le está diciendo al navegador "Para todos los elementos con un atributo tooltip que no tengan un atributo flow, o tengan flow con un valor que comienza con 'up': aplica estos estilos a su pseudo-elemento ::before."

Estamos usando un patrón aquí así que estos pueden ser extendidos a otros flows sin necesidad de repetir tanto CSS. Este patrón flow^="up" está usando el emparejador ^= (comienza con). Esto permite a los estilos aplicar también a arriba-derecha y arriba-izquierda si quisieras agregar estos controles de flujo. No vamos a cubrir estos aquí, pero puedes verlos en uso en mi demo original de descripciones emergentes en CodePen.

Aquí están los bloques CSS para los cuatro flujos que cubre este tutorial.

Arriba (por defecto):

1
/* ONLY the ::before */
2
[tooltip]:not([flow])::before,
3
[tooltip][flow^="up"]::before {
4
    bottom: 100%;
5
    border-bottom-width: 0;
6
    border-top-color: #333;
7
}
8
9
/* ONLY the ::after */
10
[tooltip]:not([flow])::after,
11
[tooltip][flow^="up"]::after {
12
    bottom: calc(100% + 5px);
13
}
14
15
/* Both ::before & ::after */
16
[tooltip]:not([flow])::before,
17
[tooltip]:not([flow])::after,
18
[tooltip][flow^="up"]::before,
19
[tooltip][flow^="up"]::after {
20
    left: 50%;
21
    transform: translate(-50%, -.5em);
22
}

Abajo:

1
[tooltip][flow^="down"]::before {
2
    top: 100%;
3
    border-top-width: 0;
4
    border-bottom-color: #333;
5
}
6
7
[tooltip][flow^="down"]::after {
8
    top: calc(100% + 5px);
9
}
10
11
[tooltip][flow^="down"]::before,
12
[tooltip][flow^="down"]::after {
13
    left: 50%;
14
    transform: translate(-50%, .5em);
15
}

Izquierda:

1
[tooltip][flow^="left"]::before {
2
    top: 50%;
3
    border-right-width: 0;
4
    border-left-color: #333;
5
    left: calc(0em - 5px);
6
    transform: translate(-.5em, -50%);
7
}
8
9
[tooltip][flow^="left"]::after {
10
    top: 50%;
11
    right: calc(100% + 5px);
12
    transform: translate(-.5em, -50%);
13
}

Derecha:

1
[tooltip][flow^="right"]::before {
2
    top: 50%;
3
    border-left-width: 0;
4
    border-right-color: #333;
5
    right: calc(0em - 5px);
6
    transform: translate(.5em, -50%);
7
}
8
9
[tooltip][flow^="right"]::after {
10
    top: 50%;
11
    left: calc(100% + 5px);
12
    transform: translate(.5em, -50%);
13
}

7. Anima Todas las Cosas

Las animaciones son increíbles. Las animaciones pueden:

  • ayudar a los usuarios a sentirse cómodos
  • ayudar a los usuarios con la conciencia especial de tu UI
  • llamar la atención a cosas que necesitan ser vistas
  • suavizar elementos de una UI que de otra manera tendrían un efecto binario de encendido/apagado discorde

Nuestras descripciones emergentes caen en la última descripción. En vez de que una burbuja de texto exista de repente y aparezca en un flash, hagámoslas más suaves.

@keyframes

Necesitaremos dos animaciones @keyframe. Las descripciones emergentes arriba/abajo usarán el fotograma tooltips-vert, y las descripciones emergentes izquierda/derecha usarán el fotograma tooltips-horz. Nota en ambos de estos fotogramas que solo estamos definiendo el estado final deseado de las descripciones emergentes. No necesitamos saber de donde vienen (las descripciones emergentes mismas tienen esa información de estilo). Solo queremos controlar a donde irán.

1
@keyframes tooltips-vert {
2
  to {
3
    opacity: .9;
4
    transform: translate(-50%, 0);
5
  }
6
}
7
8
@keyframes tooltips-horz {
9
  to {
10
    opacity: .9;
11
    transform: translate(0, -50%);
12
  }
13
}

Ahora, necesitamos aplicar estos fotogramas a las descripciones cuando un usuario pasa sobre los elementos disparadores (los elementos con atributos [tooltip]). Ya que estamos empleando varios flujos para controlar como se mostrarán las descripciones emergentes, necesitamos identificar esas posibilidades en los estilos.

Usa :hover para Pasar Control a Animaciones

1
[tooltip]:not([flow]):hover::before,
2
[tooltip]:not([flow]):hover::after,
3
[tooltip][flow^="up"]:hover::before,
4
[tooltip][flow^="up"]:hover::after,
5
[tooltip][flow^="down"]:hover::before,
6
[tooltip][flow^="down"]:hover::after {
7
    animation: 
8
        tooltips-vert 
9
        300ms 
10
        ease-out
11
        forwards;
12
}
13
14
[tooltip][flow^="left"]:hover::before,
15
[tooltip][flow^="left"]:hover::after,
16
[tooltip][flow^="right"]:hover::before,
17
[tooltip][flow^="right"]:hover::after {
18
    animation: 
19
        tooltips-horz 
20
        300ms 
21
        ease-out 
22
        forwards;
23
}

Recuerda que no podemos animar la propiedad display, pero podemos darle a las descripciones emergentes un efecto de desvanecimiento manipulando opacity. También estamos animando la propiedad transform que da a las descripciones emergentes un movimiento sutil como si estuvieran volando al punto de sus elementos disparadores.

Nota la palabra clave forwards en la declaración de animación. Esto le dice a la animación que no se reinicie una vez que se complete, sino que continúe adelante y se quede en el final.

Conclusión

¡Fantástico trabajo! Cubrimos mucho en este tutorial, y ahora tenemos una estupenda colección de descripciones emergentes para mostrar nuestro arduo trabajo:

Solo hemos rascado la superficie de lo que puede hacerse con descripciones emergentes CSS. ¡Diviértete jugando con ellas y sigue experimentando e inventando tus propias recetas!

Más Tutoriales CSS UI

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.