
✨ Animation de lignes SVG et de tracés fermés avec du CSS pur
L’animation de contour SVG fait partie de ces techniques qui transforment une icône statique en illustration vivante. Vous avez probablement déjà vu cet effet: le tracé d’un logo se dessine tout seul, comme si une plume invisible suivait la forme du début à la fin. Le rendu fait premium, mais il est obtenu uniquement avec du CSS.
Le problème, c’est que la plupart des tutoriels s’arrêtent au cas le plus simple: un tracé ouvert, une ligne unique, une animation du début vers la fin. Or les graphiques réels comportent des contours fermés, des formes fragmentées et des sens de dessin que le designer n’a pas maîtrisés. Un tracé SVG peut commencer n’importe où, et vous avez besoin qu’il se dessine dans le sens horaire à partir d’un point de départ esthétiquement satisfaisant.
Voici le jeu complet de techniques: de l’animation de base aux doubles lignes en passant par le contrôle total des points de départ et d’arrivée. Le tout en CSS pur, sans bibliothèque ni mesure en cours d’exécution. Ces méthodes ont été testées lors du développement du plugin SVG Divider et fonctionnent dans tous les navigateurs modernes.
💡 Aperçu rapide:
- Relevez la longueur du tracé SVG via
getTotalLength()ou Illustrator et inscrivez la valeur en dur dans le CSS. - Définissez
stroke-dasharray: LENGTHet animezstroke-dashoffsetdeLENGTHvers0. - Pour inverser le sens, permutez le trait et le vide dans
stroke-dasharrayet poussezstroke-dashoffsetvers l’avant. - Décalez le point de départ en ajoutant la moitié (ou toute autre fraction) de la longueur à
stroke-dashoffset. - Lancez une animation «de l’intérieur vers l’extérieur»: partez de
HALF_LENGTH, terminez àFULL_LENGTH. - Mettez en place des doubles lignes via un
stroke-dasharrayà demi-longueur et unstroke-dashoffsetdécalé d’un quart.
Fondements techniques: traits, vides et longueur de tracé
Toute animation SVG repose sur deux propriétés CSS: stroke-dasharray et stroke-dashoffset. La première définit un motif «trait-vide» le long du contour, la seconde décale ce motif. Si vous faites en sorte que le trait soit égal à la longueur totale du tracé puis animez le décalage, la ligne se «dessine» sous vos yeux.
L’étape clé avant toute animation consiste à relever la longueur totale du tracé. Méthodes:
- JavaScript:
document.querySelector('path').getTotalLength(), un appel dans la console, la valeur est inscrite en dur dans le CSS. Pas d’exécution en cours de route. - Illustrator: le panneau «Informations sur le document» affiche la longueur du tracé sélectionné.
- Script personnalisé: si vous avez des dizaines ou des centaines de tracés, il est pertinent d’écrire un parcours automatique avec balisage des longueurs.
Nuance importante: getTotalLength() et Illustrator peuvent donner des valeurs légèrement différentes pour un même tracé. La raison tient à une précision de calcul différente. L’écart se situe généralement dans une fourchette de 1 à 2 unités, sans incidence visuelle.
Vérifiez la géométrie du tracé pour détecter d’éventuelles erreurs. Le sens de dessin et le point de départ dépendent de la manière dont le designer a construit la courbe dans l’éditeur, c’est normal. Nous allons voir plus bas comment maîtriser les deux sans modifier le SVG lui-même.
Animation de base: dessiner une ligne du début à la fin
Cas le plus simple: un tracé ouvert d’une longueur de, disons, 100 unités. Définissez le trait sur la longueur totale et animez le décalage de 100 vers 0:
1 @keyframes reveal { 2 to { 3 stroke-dashoffset: 0; 4 } 5 } 6 svg path { 7 stroke-dashoffset: 100; 8 stroke-dasharray: 100; 9 animation: reveal 1s ease-in-out 0s forwards; 10 }
Voici ce qui se passe: stroke-dasharray: 100 définit 100 unités de trait plein et 100 unités d’espace vide (la seconde valeur est par défaut égale à la première). stroke-dashoffset: 100 décale le motif de sorte que la partie visible sorte des limites du tracé, la ligne est invisible. L’animation réduit le décalage jusqu’à zéro, et le trait se met en place progressivement.
Quelques remarques pratiques:
- Remplacez
FULL_LENGTHpar la valeur réelle, sans unité de mesure. Le moteur CSS ne comprend paspxouemà l’intérieur destroke-dasharray. - Le sélecteur
svg pathcible un seul contour. Si le SVG comporte plusieurs tracés, utilisez des classes, des identifiants ou des pseudo-classes commepath:nth-of-type(3). Outils de débogage::nth Testeret nthmaster.com. - Le nom de la
@keyframesdoit être unique pour chaque variante d’animation. Des tracés différents nécessitent souvent leurs propres keyframes. - Évitez les valeurs négatives pour
stroke-dashoffset: Safari peut présenter des scintillements ou des artefacts visuels avec des décalages négatifs.
Contrôler le sens: inverser le dessin
Par défaut, l’animation va du début du tracé vers la fin, quel que soit l’endroit où le designer a tracé la courbe. Mais vous avez souvent besoin de l’inverse: un contour fermé qui se dessine dans le sens horaire au lieu du sens antihoraire.
La solution consiste à inverser le motif de trait: la ligne commence invisible (0 trait, 100 vide) et devient visible (100 trait, 0 vide), tandis que le décalage la tire vers l’arrière:
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 } 11 svg path { 12 animation: reversed 1s ease-in-out 0s forwards; 13 }
Le mécanisme repose sur la nature cyclique du motif de trait: la ligne pleine apparaît à l’extrémité du tracé, tandis que sa copie part vers la gauche au-delà du début et reste invisible. La même chose se produit sur les contours fermés: la copie du trait apparaît «avant» le début et ne perturbe pas la perception.
Il existe une approche alternative, plus courte et sans manipulation du tableau:
1 @keyframes alternative-reversed { 2 from { 3 stroke-dashoffset: 100; 4 } 5 to { 6 stroke-dashoffset: 200; 7 } 8 } 9 svg path { 10 stroke-dasharray: 100; 11 animation: alternative-reversed 1s ease-in-out 0s forwards; 12 }
Ici, stroke-dasharray est fixé à la longueur totale, tandis que le décalage passe de 100 à 200. Même résultat, le trait se dessine en sens inverse. Utilisez la variante qui vous semble la plus intuitive.
Décaler le point de départ
Un tracé fermé est comme une voie ferrée circulaire: le train peut partir de n’importe quelle gare. L’objectif est de déplacer le début de l’animation vers un point esthétiquement plaisant sans toucher à la géométrie elle-même.
Commencer du côté opposé
Pour les contours symétriques, un décalage d’une demi-longueur suffit:
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 } 11 svg path { 12 animation: start-from-other-side 1s ease-in-out 0s forwards; 13 }
Le sens du dessin reste celui d’origine, mais visuellement l’animation démarre depuis l’extrémité opposée.
Inverser le sens et choisir un point de départ arbitraire
Pour inverser le sens et décaler le point de départ simultanément, ajoutez la longueur totale au décalage 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 } 11 svg path { 12 animation: other-side-and-reverse 1s ease-in-out 0s forwards; 13 }
Pour un point complètement arbitraire, remplacez 50 par n’importe quelle valeur. Par tâtonnement (plus ou moins 5 à 10 unités), vous trouverez la position optimale. Sur un projet, le point de départ d’une icône de bit Twitch a été décalé de 17 pixels, un chiffre peu élégant mais visuellement parfait.
Animation «de l’intérieur vers l’extérieur»
Le trait s’allonge depuis le milieu dans les deux directions simultanément, une technique classique pour les logos et les infographies:
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 } 11 svg path { 12 animation: inside-out 1s ease-in-out 0s forwards; 13 }
Le décalage commence à la moitié de la longueur (centre du tracé) et va jusqu’à la longueur totale, en tirant le trait avec lui. Pour les formes asymétriques, le point de départ peut être décalé en plus:
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 }
Ici, 84 = DEMI_LONGUEUR + 34. La constante 34 est choisie manuellement pour une forme spécifique. Il n’y a pas de recette universelle: essayez, observez, ajustez.
Animation «de l’extérieur vers l’intérieur»: le double stylo
L’approche inverse: le trait se dessine depuis les deux extrémités simultanément et converge vers le milieu. Sur les contours ouverts, cela donne un effet «deux stylos»:
1 @keyframes outside-in { 2 from { 3 stroke-dasharray: 0 100; 4 } 5 to { 6 stroke-dasharray: 50 0; 7 } 8 } 9 svg path { 10 animation: outside-in 1s ease-in-out 0s forwards; 11 }
Le trait n’atteint que la moitié de la longueur, l’écart se résorbe deux fois plus vite que dans l’animation de base. stroke-dashoffset n’est pas nécessaire ici: le motif «écart nul» à l’état final fait converger les deux moitiés du trait par lui-même.
Contrôle total: points de départ et d’arrivée
Quand une seule direction et un seul point de départ ne suffisent pas, vous pouvez contrôler les deux limites du dessin. Deux têtes de trait mobiles convergent vers une destination commune:
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 } 11 svg path { 12 animation: custom-start-end 1s ease-in-out 0s forwards; 13 }
Les valeurs 30 et 80 sont arbitraires; la seule règle stricte est que le décalage from soit inférieur au décalage to. Si les points sont proches, un segment avance vite, l’autre rampe lentement, c’est normal et même esthétique.
N’ayez pas peur de dépasser la longueur totale dans la valeur to. stroke-dashoffset: 130 avec une longueur de 100 est valide, cela décale simplement le cycle du trait au deuxième tour. L’essentiel est d’éviter les valeurs négatives.
Doubles lignes et effets spéciaux
Le mode le plus flexible: des traits d’une demi-longueur avec un décalage d’un quart. Chaque tracé reçoit deux têtes de trait qui se déplacent indépendamment:
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 } 11 svg path { 12 animation: double-lines 1s ease-in-out 0s forwards; 13 }
Pour les formes complexes, le tableau de pointillés peut être composé de plusieurs éléments. La somme de toutes les valeurs du tableau doit être égale à la longueur totale. Exemple concret pour un signe infini:
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 } 11 svg .infinity { 12 animation: infinity-double-lines 8s ease-in-out 0s alternate infinite; 13 stroke: #8D69D8; 14 }
Quatre composants du tableau (53 + 47 = 100 = longueur totale) échangent leurs places entre from et to. L’animation boucle (infinite) et s’inverse (alternate), créant un contour méditatif et respirant qui ne se répète jamais à l’identique.
Vidéo: l’animation SVG en pratique
Pour voir toutes les techniques décrites en action et comprendre les nuances de mise en œuvre, regardez ce tutoriel en anglais:
L’auteur montre la création pas à pas d’une illustration SVG animée, de l’export depuis Figma jusqu’aux finitions CSS. Les timecodes dans la description vous permettent d’accéder directement à la section qui vous intéresse.
⁉️🤔 Foire aux questions
Pourquoi connaître la longueur du tracé à l’avance s’il existe getTotalLength()?
getTotalLength()est du JavaScript, et notre objectif est d’utiliser du CSS pur, sans dépendance d’exécution. Vous mesurez la longueur UNE SEULE FOIS (dans la console ou Illustrator), vous inscrivez la valeur en dur dans le CSS, et l’animation fonctionne sans une seule ligne de JS.
Peut-on animer plusieurs tracés avec une seule animation?
Oui, s’ils ont la même longueur et le même comportement souhaité. En pratique, les tracés correspondent rarement: il est plus simple de donner à chacun son propre
@keyframesou d’utiliser des variables CSS avec des valeurs de longueur différentes.
Pourquoi Safari scintille-t-il avec un stroke-dashoffset négatif?
Il s’agit d’un bug de rendu WebKit connu: les valeurs de décalage négatives sont parfois interprétées comme une réinitialisation instantanée à 0. La solution consiste à toujours garder
stroke-dashoffset≥ 0; si vous avez besoin d’un décalage, ajoutez la longueur totale au lieu de passer en négatif.
Que faire si l’animation «saccade» au début ou à la fin?
Ajoutez
forwardsàanimation(cela préserve l’état final) et supprimezalternatesi vous n’avez pas besoin d’inversion. Vérifiez également les conflits avec d’autres règles CSS pour le même élément, par exemple unetransitionsur la même propriété.
Cela fonctionne-t-il avec stroke-dasharray sur des contours fermés à la géométrie complexe?
Oui, le mécanisme est le même pour tous les tracés SVG: lignes droites, courbes de Bézier, polygones fermés. La seule différence est que sur un contour fermé, il n’y a pas de «début» ni de «fin» visuels, donc le contrôle du point de départ est particulièrement important pour l’esthétique.
Est-ce que cela vaut la peine d’écrire l’animation manuellement alors qu’il existe des bibliothèques?
En bref: cela dépend de l’échelle. Pour une icône unique sur une page d’atterrissage, le contrôle manuel donne des résultats parfaits sans dépendance supplémentaire. Quinze minutes pour ajuster un décalage, et le contour se dessine exactement comme vous l’aviez prévu, et non comme le développeur de la bibliothèque l’a décidé.
Lorsque nous avons créé les séparateurs SVG pour Elementor, le contrôle manuel a été trois fois plus rentable. Le plugin utilise des dizaines de séparateurs animés, chacun avec des traits réglés individuellement. Aucune bibliothèque n’offrirait un tel contrôle sur l’esthétique.
En plus des techniques présentées dans cet article, vous pouvez superposer:
- Le contrôle de l’état de l’animation via JavaScript (démarrage/arrêt/redémarrage);
- Le lancement différé via
Intersection Observer, le contour ne se dessine que lorsqu’il entre dans la fenêtre d’affichage; - Les chaînes d’animation via
animation-delay; - Les fonctions d’accélération personnalisées (
cubic-bezier()); - Un travail supplémentaire sur l’opacité dans
@keyframes; - L’animation élastique des lignes en pointillés («fourmis en marche»).
Prenez les schémas de cet article comme base, substituez vos propres valeurs de longueur et expérimentez avec cubic-bezier(). Une fonction d’accélération bien choisie modifie davantage la perception de l’animation qu’un déplacement du point de départ de quelques pixels.



