Search code examples
javascriptcssgradientlinear-gradients

Gradient moving background


I am trying to recreate the background of this site in a wordpress site I am creating. I think this comes with a lottie animation but not exactly sure. I can recreate a gradient transition as seen from this stackoverflow answer but still doesnt do the trick for me. I can recreate it with something like

background: radial-gradient(ellipse at top, #e66465, transparent),
            radial-gradient(ellipse at bottom, #4d9f0c, transparent);

but the closest thing I achieve is something like this: https://jsfiddle.net/xsf85m9c/ Any ideas?

body {
  margin: 0;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: Arial, sans-serif;
  background-size: 200% 200%;
  animation: animateBackground 15s infinite linear;
  overflow: hidden;
}

@keyframes animateBackground {
  0% {
    background-position: 0% 50%;
    background: linear-gradient(120deg, #e66465, #4d9f0c);
  }
  25% {
    background-position: 50% 50%;
    background: linear-gradient(120deg, #ff9a9e, #d4fc79);
  }
  50% {
    background-position: 100% 50%;
    background: linear-gradient(120deg, #c94b4b, #4b134f);
  }
  75% {
    background-position: 150% 50%;
    background: linear-gradient(120deg, #4d9f0c, #e66465);
  }
  100% {
    background-position: 200% 50%;
    background: linear-gradient(120deg, #ff9a9e, #d4fc79);
  }
}


Solution

  • It is done using a canvas, not CSS. Let's create a similar effect. It's called plasma and I've adapted from here live demo

    Of course, you can play with the parameters like I have.

    function colorToRgb(color) {
      return {
        r: 255,
        g: 216 + 32 * Math.cos(color * Math.PI),
        b: 216 + 32 * Math.sin(color * Math.PI)
      };
    }
    
    function setPixel(ctx, x, y, rgb) {
      var index = (x + y * ctx.canvas.width) * 4;
      var pixels = ctx.canvasImageData.data;
      pixels[index] = rgb.r;
      pixels[index + 1] = rgb.g;
      pixels[index + 2] = rgb.b;
      pixels[index + 3] = 255;
    }
    
    function calcPlasma(ctx, x, y, time) {
      var size = ctx.canvas.width / 2;
      var result = 0;
    
      result += Math.sin(x / size + time);
      result += Math.sin((y / size + time) / 2.0);
      result += Math.sin((x / size + y / size + time) / 2.0);
    
      var cx = x / size / 10 + 0.8 * Math.sin(time / 4);
      var cy = y / size / 10 + 0.8 * Math.cos(time / 3);
      result += Math.sin(Math.sqrt(100 * (cx * cx + cy * cy + 1)) + time);
    
      return result;
    }
    
    
    var t = 0.0;
    
    function updateLoop(ctx) {
      var speed = 0.005;
      t = (t + speed);
    
      for (var x = 0; x < ctx.canvas.width; x++) {
        for (var y = 0; y < ctx.canvas.height; y++) {
          var color = calcPlasma(ctx, x, y, t);
          var rgb = colorToRgb(color);
          setPixel(ctx, x, y, rgb);
        }
      }
    
      ctx.canvasContext.putImageData(ctx.canvasImageData, 0, 0);
    
      requestAnimationFrame(function() {
        updateLoop(ctx);
      });
    }
    
    
    function initCanvas() {
      var canvas = document.getElementById('canvas');
      var canvasContext = canvas.getContext('2d');
    
      var canvasImageData = canvasContext.createImageData(canvas.width, canvas.height);
    
      var context = {
        canvas: canvas,
        canvasContext: canvasContext,
        canvasImageData: canvasImageData
      };
    
      return context;
    }
    
    var context = initCanvas();
    updateLoop(context);
    html,
    body {
      margin: 0;
      padding: 0;
      text-align: center;
      color: black;
    }
    
    canvas {
      width: 100%;
      height: 100vh;
      position: fixed;
      top: 0;
      left: 0;
      z-index: -1;
    }
    <canvas id="canvas"></canvas>
    
    
    <h1>some text</h1>
    
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>
    <p>content of website</p>