Skip to content

Todo para WordPress, el desarrollo web — y mucho más

✨ Animando líneas SVG y trazados cerrados con CSS puro

✨ Animando líneas SVG y trazados cerrados con CSS puro

La animación de trazo SVG es una de esas técnicas que transforman un icono estático en una ilustración viva. Seguramente ha visto este efecto: el contorno de un logotipo se dibuja suavemente solo, como si un bolígrafo invisible trazara la forma de principio a fin. Parece costoso, pero se logra con puro CSS.

El problema es que la mayoría de los tutoriales se detienen en el caso más simple: un trazado abierto, una sola línea, animación de inicio a fin. Pero los gráficos reales implican contornos cerrados, formas fragmentadas y direcciones de dibujo que el diseñador no controló. Un trazado SVG puede empezar en cualquier parte, y usted necesita que se dibuje en sentido horario desde un punto de partida estéticamente agradable.

A continuación, el conjunto completo de técnicas: desde la animación básica hasta líneas dobles y control total sobre los puntos de inicio y fin. Todo con CSS puro, sin librerías ni mediciones en tiempo de ejecución. Estos métodos se probaron durante el desarrollo del plugin SVG Divider y funcionan en cualquier navegador moderno.

💡 Resumen rápido:

  • Encuentre la longitud del trazado SVG mediante getTotalLength() o Illustrator y escriba el número en el CSS.
  • Establezca stroke-dasharray: LENGTH y anime stroke-dashoffset de LENGTH a 0.
  • Para invertir la dirección, intercambie trazo y espacio en stroke-dasharray y desplace stroke-dashoffset hacia adelante.
  • Desplace el punto de inicio sumando la mitad (o cualquier fracción) de la longitud a stroke-dashoffset.
  • Lance la animación «de dentro hacia fuera»: empiece desde HALF_LENGTH, termine en FULL_LENGTH.
  • Configure líneas dobles mediante stroke-dasharray a la mitad de la longitud y stroke-dashoffset con un cuarto de desplazamiento.

Fundamento técnico: trazos, espacios y longitud del trazado

En el núcleo de cualquier animación SVG hay dos propiedades CSS: stroke-dasharray y stroke-dashoffset. La primera define un patrón de «trazo-espacio» a lo largo del contorno, la segunda desplaza ese patrón. Si iguala el trazo a la longitud total del trazado y luego anima el desplazamiento, la línea se «dibuja» ante sus ojos.

El paso clave antes de cualquier animación es hallar la longitud total del trazado. Métodos:

  • JavaScript: document.querySelector('path').getTotalLength(), una llamada en consola, el número se escribe directamente en el CSS. Sin tiempo de ejecución.
  • Illustrator: el panel «Información del documento» muestra la longitud del trazado seleccionado.
  • Script personalizado: si tiene decenas o cientos de trazados, tiene sentido escribir un recorrido automático y marcado de longitud.

Matiz importante: getTotalLength() e Illustrator pueden dar números ligeramente distintos para el mismo trazado. La razón es la diferente precisión de cálculo. La discrepancia suele estar dentro de 1 o 2 unidades y no afecta al aspecto visual.

Revise la geometría del trazado en busca de errores. La dirección de dibujo y el punto de inicio dependen de cómo el diseñador construyó la curva en el editor, eso es normal. Más abajo aprenderemos a controlar ambos sin editar el propio SVG.

Animación básica: dibujar una línea de principio a fin

El caso más simple: un trazado abierto con una longitud de, digamos, 100 unidades. Establezca el trazo a la longitud total y anime el desplazamiento de 100 a 0:

1@keyframes reveal {
2 to {
3 stroke-dashoffset: 0;
4 }
5}
6svg path {
7 stroke-dashoffset: 100;
8 stroke-dasharray: 100;
9 animation: reveal 1s ease-in-out 0s forwards;
10}

Lo que ocurre aquí: stroke-dasharray: 100 establece 100 unidades de línea continua y 100 unidades de espacio vacío (el segundo valor toma por defecto el primero). stroke-dashoffset: 100 desplaza el patrón de modo que la parte visible queda fuera de los límites del trazado, la línea es invisible. La animación reduce el desplazamiento a cero y el trazo avanza hasta colocarse en su sitio.

Algunas notas prácticas:

  • Sustituya FULL_LENGTH por el número real sin unidades de medida. El motor CSS no entiende px ni em dentro de stroke-dasharray.
  • El selector svg path es para un contorno. Si el SVG tiene múltiples trazados, use clases, IDs o pseudoclases como path:nth-of-type(3). Herramientas de depuración: :nth Tester y nthmaster.com.
  • El nombre de @keyframes debe ser único para cada variante de animación. Distintos trazados suelen requerir sus propios keyframes.
  • Evite valores negativos de stroke-dashoffset: Safari puede parpadear o mostrar artefactos con desplazamientos negativos.

Controlar la dirección: invertir el dibujo

Por defecto, la animación va del inicio al final del trazado, dondequiera que el diseñador dibujara la curva. Pero a menudo necesita lo contrario: un contorno cerrado que se dibuje en sentido horario en lugar de antihorario.

La solución consiste en invertir el patrón de trazo: la línea empieza invisible (0 trazo, 100 espacio) y se vuelve visible (100 trazo, 0 espacio), mientras el desplazamiento tira de ella hacia atrás:

1@keyframes reversed {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 0;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 100;
9 }
10}
11svg path {
12 animation: reversed 1s ease-in-out 0s forwards;
13}

La mecánica funciona gracias a la naturaleza cíclica del patrón de trazo: la línea continua se materializa en el extremo final del trazado, mientras su copia se va hacia la izquierda más allá del inicio y permanece invisible. Lo mismo ocurre en contornos cerrados: la copia del trazo aparece «antes» del inicio y no interfiere en la percepción.

Existe un enfoque alternativo, más corto y sin manipulación del array:

1@keyframes alternative-reversed {
2 from {
3 stroke-dashoffset: 100;
4 }
5 to {
6 stroke-dashoffset: 200;
7 }
8}
9svg path {
10 stroke-dasharray: 100;
11 animation: alternative-reversed 1s ease-in-out 0s forwards;
12}

Aquí stroke-dasharray se fija en la longitud total, mientras que el desplazamiento va de 100 a 200. Mismo resultado, la línea se dibuja en dirección inversa. Use la variante que le resulte más intuitiva.

Cambiar el punto de inicio

Un trazado cerrado es como una vía de tren circular: el tren puede arrancar desde cualquier estación. La tarea consiste en desplazar el inicio de la animación a un punto estéticamente agradable sin tocar la geometría en sí.

Comenzar desde el lado opuesto

Para contornos simétricos, basta con un desplazamiento de la mitad de la longitud:

1@keyframes start-from-other-side {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 50;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 50;
9 }
10}
11svg path {
12 animation: start-from-other-side 1s ease-in-out 0s forwards;
13}

La dirección de dibujo sigue siendo la original, pero visualmente la animación arranca desde el extremo opuesto.

Invertir la dirección y punto de inicio arbitrario

Para invertir simultáneamente la dirección y desplazar el punto de inicio, sume la longitud total al desplazamiento final:

1@keyframes other-side-and-reverse {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 50;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 150;
9 }
10}
11svg path {
12 animation: other-side-and-reverse 1s ease-in-out 0s forwards;
13}

Para un punto completamente arbitrario, sustituya cualquier valor en lugar de 50. El ensayo y error (más o menos 5-10 unidades) encuentra la posición óptima. En un proyecto, el punto de inicio en un icono de bits de Twitch se desplazó 17 píxeles, un número feo pero visualmente perfecto.

Animación «de dentro hacia fuera»

La línea crece desde el centro en ambas direcciones simultáneamente, una técnica clásica para logotipos e infografías:

1@keyframes inside-out {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 50;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 100;
9 }
10}
11svg path {
12 animation: inside-out 1s ease-in-out 0s forwards;
13}

El desplazamiento comienza desde la mitad de la longitud (centro del trazado) y llega hasta la longitud total, arrastrando el trazo consigo. Para formas asimétricas, el punto de inicio puede desplazarse adicionalmente:

1@keyframes custom-inside-out {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 84;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 134;
9 }
10}

Aquí 84 = MITAD_DE_LONGITUD + 34. La constante 34 se elige manualmente para una forma específica. No existe una receta universal: pruebe, observe, ajuste.

Animación «de fuera hacia dentro»: doble pluma

El enfoque opuesto: la línea se dibuja desde ambos extremos simultáneamente, convergiendo hacia el centro. En contornos abiertos esto produce un efecto de «dos plumas»:

1@keyframes outside-in {
2 from {
3 stroke-dasharray: 0 100;
4 }
5 to {
6 stroke-dasharray: 50 0;
7 }
8}
9svg path {
10 animation: outside-in 1s ease-in-out 0s forwards;
11}

El trazo alcanza solo la mitad de la longitud, el espacio se colapsa el doble de rápido que en la animación básica. Aquí no se necesita stroke-dashoffset: el patrón de «0 de espacio» en el estado final hace por sí mismo que ambas mitades del trazo converjan.

Control total: puntos de inicio y fin

Cuando una sola dirección y un punto de inicio no bastan, usted puede controlar ambos límites del dibujo. Dos cabezales de línea móviles convergen hacia un destino común:

1@keyframes custom-start-end {
2 from {
3 stroke-dasharray: 0 100;
4 stroke-dashoffset: 30;
5 }
6 to {
7 stroke-dasharray: 100 0;
8 stroke-dashoffset: 80;
9 }
10}
11svg path {
12 animation: custom-start-end 1s ease-in-out 0s forwards;
13}

Los valores 30 y 80 son arbitrarios; que el desplazamiento from sea menor que el desplazamiento to es la única regla estricta. Si los puntos están cerca, un segmento vuela rápido y el otro se arrastra lentamente, eso es normal e incluso hermoso.

No tema ir más allá de la longitud total en el valor to. stroke-dashoffset: 130 con longitud 100 es válido, simplemente desplaza el ciclo del trazo a la segunda vuelta. Lo principal es evitar valores negativos.

Líneas dobles y efectos especiales

El modo más flexible: trazos de media longitud con desplazamiento de un cuarto. Cada trazado obtiene dos cabezales de línea que se mueven de forma independiente:

1@keyframes double-lines {
2 from {
3 stroke-dasharray: 0 50;
4 stroke-dashoffset: 25;
5 }
6 to {
7 stroke-dasharray: 50 0;
8 stroke-dashoffset: 50;
9 }
10}
11svg path {
12 animation: double-lines 1s ease-in-out 0s forwards;
13}

Para formas complejas, el arreglo de trazos puede constar de múltiples componentes. La suma de todos los valores del arreglo debe igualar la longitud total. Ejemplo real para un signo de infinito:

1@keyframes infinity-double-lines {
2 from {
3 stroke-dasharray: 0 53 0 47;
4 stroke-dashoffset: 37;
5 }
6 to {
7 stroke-dasharray: 53 0 47 0;
8 stroke-dashoffset: 60;
9 }
10}
11svg .infinity {
12 animation: infinity-double-lines 8s ease-in-out 0s alternate infinite;
13 stroke: #8D69D8;
14}

Cuatro componentes del arreglo (53 + 47 = 100 = longitud total) intercambian lugares entre from y to. La animación se repite en bucle (infinite) y se invierte (alternate), creando un contorno respiratorio y meditativo que nunca se repite de forma idéntica.

Vídeo: animación SVG en la práctica

Para ver todas las técnicas descritas en vivo y entender los matices de la configuración, vea este tutorial en inglés:

El autor muestra la creación paso a paso de una ilustración SVG animada, desde la exportación desde Figma hasta los toques finales de CSS. Las marcas de tiempo en la descripción le permiten saltar directamente a la sección que necesite.

⁉️🤔 Preguntas frecuentes

¿Por qué conocer la longitud de la ruta de antemano si existe getTotalLength()?

getTotalLength() es JavaScript, y nuestro objetivo es CSS puro sin dependencias en tiempo de ejecución. Usted mide la longitud UNA VEZ (en la consola o en Illustrator), codifica el número en el CSS y la animación funciona sin una sola línea de JS.

¿Se pueden animar múltiples rutas con una sola animación?

Sí, si tienen la misma longitud y el comportamiento deseado. En la práctica, las rutas rara vez coinciden; es más sencillo dar a cada una su propio @keyframes o usar variables CSS con diferentes valores de longitud.

¿Por qué Safari parpadea con stroke-dashoffset negativo?

Es un error de renderizado conocido de WebKit: los valores de desplazamiento negativos a veces se interpretan como un reinicio instantáneo a 0. La solución es mantener siempre stroke-dashoffset ≥ 0; si necesita un desplazamiento, añada la longitud completa en lugar de usar valores negativos.

¿Qué hacer si la animación da un "tirón" al inicio o al final?

Añada forwards a animation (conserva el estado final) y elimine alternate si no necesita inversión. Compruebe también si hay conflictos con otras reglas CSS para el mismo elemento, por ejemplo, una transition en la misma propiedad.

¿Funciona esto con stroke-dasharray en contornos cerrados con geometría compleja?

Sí, la mecánica es la misma para cualquier ruta SVG, líneas rectas, curvas Bézier o polígonos cerrados. La única diferencia es que en un contorno cerrado no hay un "inicio" y un "final" visuales, por lo que controlar el punto de partida es especialmente importante para la estética.

¿Vale la pena escribir la animación manualmente cuando existen librerías?

Respuesta corta: depende de la escala. Para un icono puntual en una página de aterrizaje, el control manual ofrece resultados perfectos sin dependencias adicionales. Quince minutos ajustando un desplazamiento y el contorno se dibuja exactamente como usted pretendía, no como decidió el desarrollador de la librería.

Cuando hicimos los divisores SVG para Elementor, el control manual se amortizó con creces. El plugin utiliza docenas de divisores animados, cada uno con trazos ajustados individualmente. Ninguna librería ofrecería tal control sobre la estética.

Sobre las técnicas de este artículo, usted puede superponer:

  • Control del estado de la animación mediante JavaScript (iniciar/detener/reiniciar);
  • Lanzamiento diferido mediante Intersection Observer: el contorno se dibuja solo cuando entra en la ventana gráfica;
  • Cadenas de animación mediante animation-delay;
  • Funciones de aceleración personalizadas (cubic-bezier());
  • Trabajo adicional de opacidad en @keyframes;
  • Animación elástica de líneas discontinuas ("hormigas marchantes").

Tome los planos de este artículo como base, sustituya sus valores de longitud y experimente con cubic-bezier(). Una función de aceleración bien elegida cambia la percepción de la animación más que desplazar el punto de inicio un par de píxeles.