Animated SVG scenes (<animate>, <animateMotion>) are cheap, but ten of them still run every frame when they are scrolled away. Every root <svg> has pauseAnimations(), unpauseAnimations() and setCurrentTime():
const io = new IntersectionObserver((entries) => entries.forEach((e) => {
const svg = e.target as SVGSVGElement;
if (e.isIntersecting) svg.unpauseAnimations(); else svg.pauseAnimations();
}));
document.querySelectorAll('svg.scene').forEach((s) => io.observe(s));With prefers-reduced-motion, pause everything and setCurrentTime() to a representative frame instead.