SVG · Démo interactive

SVG avancé
au-delà des icônes

Le SVG ne sert pas qu'à afficher des logos. Tracés qui se dessinent, gradients, masques, filtres, motifs, animation le long d'un chemin — six techniques natives, illustrées en direct.

01

stroke-dashoffset — tracé animé

En jouant sur stroke-dasharray et stroke-dashoffset, on fait « dessiner » un tracé comme à la main. Parfait pour signatures, logos animés ou illustrations qui se révèlent au scroll.

<svg class="trace play" viewBox="0 0 300 120" fill="none">
  <path pathLength="1"
        d="M10,80 C40,10 70,10 90,60 S140,115 165,60 S215,5 250,50 C272,72 288,60 292,38" />
</svg>
<button id="replay">Rejouer le tracé</button>
.trace { width: 300px; }
.trace path {
  fill: none; stroke: #c9952a; stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
  /* pathLength="1" normalise la longueur → on raisonne en 0–1 */
  stroke-dasharray: 1;
  stroke-dashoffset: 1;              /* tracé masqué */
}
.trace.play path { animation: draw 1.8s ease forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }   /* tracé révélé */
const svg = document.querySelector('.trace');

document.getElementById('replay').addEventListener('click', () => {
  svg.classList.remove('play');
  void svg.getBoundingClientRect();   // force un reflow → relance l'animation
  svg.classList.add('play');
});
02

Gradients SVG

linearGradient et radialGradient offrent un contrôle bien plus fin que le CSS : plusieurs stops, positions précises, et animation des couleurs via SMIL (<animate>) — sans une ligne de JS.

<svg viewBox="0 0 320 120">
  <defs>
    <linearGradient id="lin" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#C9952A" />
      <stop offset="1" stop-color="#4577e8" />
    </linearGradient>
    <radialGradient id="rad" cx="0.5" cy="0.5" r="0.5">
      <stop offset="0" stop-color="#f7c66b" />
      <stop offset="1" stop-color="#1B2A4A" />
    </radialGradient>
    <!-- couleurs animées via SMIL, sans JS -->
    <linearGradient id="anim" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0" stop-color="#C9952A">
        <animate attributeName="stop-color"
          values="#C9952A;#4577e8;#c586c0;#C9952A" dur="6s" repeatCount="indefinite" />
      </stop>
      <stop offset="1" stop-color="#4577e8">
        <animate attributeName="stop-color"
          values="#4577e8;#c586c0;#C9952A;#4577e8" dur="6s" repeatCount="indefinite" />
      </stop>
    </linearGradient>
  </defs>
  <rect x="0" y="0" width="96" height="120" rx="12" fill="url(#lin)" />
  <circle cx="160" cy="60" r="52" fill="url(#rad)" />
  <rect x="224" y="0" width="96" height="120" rx="12" fill="url(#anim)" />
</svg>
03

clipPath & mask

clipPath découpe selon une forme (contour net) ; mask module l'opacité selon la luminosité (un dégradé blanc→noir crée un fondu). Deux outils complémentaires pour habiller images et blocs.

<svg viewBox="0 0 320 140">
  <defs>
    <clipPath id="clip"><circle cx="75" cy="70" r="62" /></clipPath>
    <linearGradient id="rainbow" x1="0" y1="0" x2="1" y2="1">
      <stop offset="0" stop-color="#C9952A" />
      <stop offset="0.5" stop-color="#c586c0" />
      <stop offset="1" stop-color="#4577e8" />
    </linearGradient>
    <linearGradient id="fade" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0" stop-color="#fff" />  <!-- blanc = visible -->
      <stop offset="1" stop-color="#000" />  <!-- noir = transparent -->
    </linearGradient>
    <mask id="mask"><rect width="150" height="100" fill="url(#fade)" /></mask>
  </defs>
  <!-- clipPath : découpe nette selon la forme -->
  <rect x="13" y="8" width="124" height="124" fill="url(#rainbow)" clip-path="url(#clip)" />
  <!-- mask : opacité modulée par la luminosité → fondu -->
  <g transform="translate(170,20)">
    <rect width="150" height="100" rx="12" fill="url(#rainbow)" mask="url(#mask)" />
  </g>
</svg>
04

pattern — motifs répétés

Un <pattern> définit une tuile réutilisée en remplissage. Points, hachures, textures… le tout vectoriel, net à toute résolution, et pilotable via patternTransform.

<svg viewBox="0 0 320 120">
  <defs>
    <pattern id="dots" width="20" height="20" patternUnits="userSpaceOnUse">
      <circle cx="10" cy="10" r="3" fill="#C9952A" />
    </pattern>
    <!-- patternTransform incline toute la tuile -->
    <pattern id="lines" width="16" height="16" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
      <line x1="0" y1="0" x2="0" y2="16" stroke="#4577e8" stroke-width="4" />
    </pattern>
  </defs>
  <rect x="0" y="0" width="150" height="120" rx="12" fill="url(#dots)" stroke="#2a3f60" />
  <rect x="170" y="0" width="150" height="120" rx="12" fill="url(#lines)" stroke="#2a3f60" />
</svg>
05

Filtres SVG — glow & goo

Les filtres composables (feGaussianBlur, feColorMatrix, feMerge) produisent des effets impossibles en CSS pur : halo lumineux, et le fameux effet « goo » où des formes fusionnent comme du liquide.

<svg viewBox="0 0 320 140">
  <defs>
    <filter id="goo">
      <feGaussianBlur in="SourceGraphic" stdDeviation="7" result="blur" />
      <!-- alpha très contrasté → les bords flous se soudent -->
      <feColorMatrix in="blur" type="matrix"
        values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" />
    </filter>
    <filter id="glow" x="-60%" y="-60%" width="220%" height="220%">
      <feGaussianBlur stdDeviation="4" result="b" />
      <feMerge><feMergeNode in="b" /><feMergeNode in="SourceGraphic" /></feMerge>
    </filter>
  </defs>
  <g filter="url(#goo)" fill="#C9952A">
    <circle cx="70" cy="70" r="20" />
    <circle class="goo-mover" cx="120" cy="70" r="20" />
  </g>
  <text x="200" y="82" filter="url(#glow)" fill="#f7c66b" font-size="34">glow</text>
</svg>
/* le 2e cercle fait des va-et-vient → il fusionne avec le 1er (effet goo) */
.goo-mover { animation: goo 2.8s ease-in-out infinite alternate; }
@keyframes goo {
  from { transform: translateX(0); }
  to   { transform: translateX(-32px); }
}
06

offset-path — animer le long d'un tracé

offset-path fait suivre à un élément un chemin arbitraire, offset-distance le fait avancer de 0 à 100 %. Placé dans le SVG, le mobile reste parfaitement aligné sur le tracé, quelle que soit la taille d'affichage.

<svg viewBox="0 0 320 120">
  <path d="M20,60 C80,-10 120,130 180,60 S280,15 300,60"
        fill="none" stroke="#2a3f60" stroke-width="2" stroke-dasharray="4 6" />
  <circle class="mover" r="8" fill="#C9952A" />
</svg>
<button id="toggle">Pause</button>
.mover {
  /* le mobile suit exactement ce tracé (le même que le <path>) */
  offset-path: path("M20,60 C80,-10 120,130 180,60 S280,15 300,60");
  offset-distance: 0%;
  animation: travel 3s linear infinite;
}
@keyframes travel { to { offset-distance: 100%; } }
svg.paused .mover { animation-play-state: paused; }
const svg = document.querySelector('svg');
const btn = document.getElementById('toggle');

btn.addEventListener('click', () => {
  const paused = svg.classList.toggle('paused');
  btn.textContent = paused ? 'Lecture' : 'Pause';
});