<svg>
  <defs>
    <linearGradient id="gradient" y2="1">
      <stop stop-color="rgb(80, 220, 255)" offset="0" />
      <stop stop-color="rgb(250, 90, 255)" offset="1" />
    </linearGradient>
  </defs>
  <rect width="100%" height="100%" fill="url(#gradient)" />
</svg>
html, body, svg {
  height: 100%
}
body {
  margin: 0
}
svg {
  width: 100%;
  vertical-align: middle
}
import animate from "https://cdnjs.cloudflare.com/ajax/libs/animateplus/2.0.1/animateplus.min.js";

const gradient = Array.from(document.querySelectorAll("stop"), (stop, index) => ({
  stop,
  colors: [
    stop.getAttribute("stop-color").match(/\d+/g).map(Number),
    index ? [255, 255, 120] : [20, 230, 100]
  ]
}));

animate({
  easing: "out-quartic",
  duration: 4000,
  loop: true,
  change: progress =>
    gradient.forEach(({stop, colors}) => {
      const [from, to] = colors;
      const [r, g, b] = from.map((value, index) =>
        Math.round(value + progress * (to[index] - value)));
      stop.setAttribute("stop-color", `rgb(${r}, ${g}, ${b})`);
      if (progress == 1) colors.reverse();
    })
});
Rerun