JSFiddle - React, Tailwind, and code Playground

by Jordan Sayner

HTML

<svg width="200" height="1000" xmlns="http://www.w3.org/2000/svg" style="position: fixed; left: 50%; transform: translateX(-50%);">
  <!-- Wiggly vertical path -->
  <path id="wigglyPath" 
        d="M100,0 Q120,50 100,100 Q80,150 100,200 Q120,250 100,300 Q80,350 100,400 Q120,450 100,500 Q80,550 100,600 Q120,650 100,700" 
        fill="transparent" 
        stroke="black" 
        stroke-width="2"
        stroke-dasharray="2000"
        stroke-dashoffset="2000">
  </path>
  
  <!-- Text following the path -->
  <text font-size="20" fill="black">
    <textPath href="#wigglyPath" startOffset="0%">
      Follow the wiggly line!
    </textPath>
  </text>
</svg>

CSS

body {
  height: 2000px; /* Make the page scrollable */
  margin: 0;
}

path {
  stroke-dasharray: 2000; /* Ensure this matches the path length */
  stroke-dashoffset: 2000; /* Hide the stroke initially */
  transition: stroke-dashoffset 0.2s ease-out;
}

JavaScript

document.addEventListener("scroll", () => {
  const path = document.querySelector("#wigglyPath");
  const textPath = document.querySelector("textPath");
  
  // Get the bounding rect and calculate the scroll progress
  const pathBounding = path.getBoundingClientRect();
  const viewportHeight = window.innerHeight;

  const progress = Math.min(
    1,
    Math.max(0, (viewportHeight - pathBounding.top) / (viewportHeight + pathBounding.height))
  );

  // Animate the line appearance
  const pathLength = path.getTotalLength();
  path.style.strokeDashoffset = pathLength * (1 - progress);

  // Move the text along the path
  textPath.setAttribute("startOffset", `${progress * 100}%`);
});