JSFiddle - React, Tailwind, and code Playground
by Jordan Sayner
HTML
<svg xmlns="http://www.w3.org/2000/svg" width="333" height="288" viewBox="0 0 333 288" fill="none" data-stroke="80">
<path d="M275.337 275.149C335.323 215.164 335.323 117.909 275.337 57.9236C215.352 -2.0616 118.097 -2.0616 58.1118 57.9236C-1.87339 117.909 -1.87339 215.164 58.1118 275.149" stroke="#E9E9E4" stroke-width="24.5763" stroke-linecap="round"/>
<path d="M275.337 275.149C335.323 215.164 335.323 117.909 275.337 57.9236C215.352 -2.0616 118.097 -2.0616 58.1118 57.9236C-1.87339 117.909 -1.87339 215.164 58.1118 275.149" stroke="red" stroke-width="24.5763" stroke-linecap="round" style="stroke-dasharray: 723.932; stroke-dashoffset: 723.932;"/>
</svg>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<svg xmlns="http://www.w3.org/2000/svg" width="333" height="288" viewBox="0 0 333 288" fill="none" data-stroke="70">
<path d="M275.337 275.149C335.323 215.164 335.323 117.909 275.337 57.9236C215.352 -2.0616 118.097 -2.0616 58.1118 57.9236C-1.87339 117.909 -1.87339 215.164 58.1118 275.149" stroke="#E9E9E4" stroke-width="24.5763" stroke-linecap="round"/>
<path d="M275.337 275.149C335.323 215.164 335.323 117.909 275.337 57.9236C215.352 -2.0616 118.097 -2.0616 58.1118 57.9236C-1.87339 117.909 -1.87339 215.164 58.1118 275.149" stroke="red" stroke-width="24.5763" stroke-linecap="round" style="stroke-dasharray: 723.932; stroke-dashoffset: 723.932;"/>
</svg>
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br /><br />
<svg xmlns="http://www.w3.org/2000/svg" width="333" height="288" viewBox="0 0 333 288" fill="none" data-stroke="12">
<path d="M275.337 275.149C335.323...
CSS
svg {
transform: scaleX(-1);
}
JavaScript
function animatePath(path, strokePercent) {
const length = path.getTotalLength();
const strokeLength = (strokePercent / 100) * length; // Calculate the desired stroke length
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length; // Start fully hidden (off-path)
// Animate stroke from fully hidden (length) to 0 (fully visible from left to right)
path.animate(
[{ strokeDashoffset: length }, { strokeDashoffset: length - strokeLength }],
{ duration: 2000, easing: "ease-out", fill: "forwards" }
);
}
const observer = new IntersectionObserver(
(entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const svg = entry.target;
const path = svg.querySelector("path:nth-of-type(2)"); // Select the animated path
const strokePercent = parseFloat(svg.getAttribute("data-stroke")) || 100;
animatePath(path, strokePercent);
observer.unobserve(svg); // Stop observing once the animation is triggered
}
});
},
{ threshold: 0.2 } // Trigger when 20% of SVG is in view
);
document.querySelectorAll("svg").forEach((svg) => observer.observe(svg));