Rainbow Cursor

A canvas trail that paints rainbow-colored lines behind the cursor. Color cycles automatically and the line width pulses — fully customizable.

Generated using Grepped's AI UI component generator — created from scratch, not pulled from a library.

cursorcanvasrainbowtrailinteractive

Live Preview — customize or regenerate this in the workspace

Loading preview…

Design Intent

A canvas-based cursor trail that draws layered colored lines following the mouse, with time-based color cycling and a sine-wave pulse on the line width.

CSS

css
* { margin: 0; padding: 0; box-sizing: border-box; }
    html, body { width: 100%; height: 100%; overflow: hidden; background: #0f0f0f; cursor: none; }
    .hint { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); font-family: sans-serif; font-size: 16px; color: #ffffff; opacity: 0.45; pointer-events: none; user-select: none; letter-spacing: 0.04em; }
    canvas { position: fixed; top: 0; left: 0; pointer-events: none; }

HTML

html
<p class="hint">Move your cursor here</p>
  <canvas id="c"></canvas>

Full Source

html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    * { margin: 0; padding: 0; box-sizing: border-box; }
    html, body { width: 100%; height: 100%; overflow: hidden; background: #0f0f0f; cursor: none; }
    .hint { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); font-family: sans-serif; font-size: 16px; color: #ffffff; opacity: 0.45; pointer-events: none; user-select: none; letter-spacing: 0.04em; }
    canvas { position: fixed; top: 0; left: 0; pointer-events: none; }
  </style>
</head>
<body>
  <p class="hint">Move your cursor here</p>
  <canvas id="c"></canvas>
  <script>
    var LENGTH = 20;
    var SIZE   = 3;
    var TRAIL  = 0.4;
    var CYCLE  = 0.004;
    var BLUR   = 0;
    var COLORS = ['#FE0000','#FD8C00','#FFE500','#119F0B','#0644B3','#C22EDC'];

    var canvas = document.getElementById('c');
    var ctx = canvas.getContext('2d', {alpha: true});
    var cur = {x: -999, y: -999};
    var pts = [];
    var initted = false;
    var t = 0;

    function resize() { canvas.width = innerWidth; canvas.height = innerHeight; }

    function lerp(c1, c2, f) {
      var r1=parseInt(c1.slice(1,3),16), g1=parseInt(c1.slice(3,5),16), b1=parseInt(c1.slice(5,7),16);
      var r2=parseInt(c2.slice(1,3),16), g2=parseInt(c2.slice(3,5),16), b2=parseInt(c2.slice(5,7),16);
      return 'rgb('+Math.round(r1+(r2-r1)*f)+','+Math.round(g1+(g2-g1)*f)+','+Math.round(b1+(b2-b1)*f)+')';
    }

    function frame() {
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      if (!initted) { requestAnimationFrame(frame); return; }
      ctx.lineJoin = 'round'; ctx.lineCap = 'round';
      if (BLUR > 0) ctx.filter = 'blur('+BLUR+'px)'; else ctx.filter = 'none';

      var sets = [], x = cur.x, y = cur.y;
      pts.forEach(function(p, i) {
        var nx = pts[i+1] ? pts[i+1].x : pts[0].x;
        var ny = pts[i+1] ? pts[i+1].y : pts[0].y;
        p.x = x; p.y = y;
        sets.push({x: x, y: y});
        x += (nx - p.x) * TRAIL;
        y += (ny - p.y) * TRAIL;
      });

      t += CYCLE;
      var off = t % 1;
      var pulse = Math.sin(t * 5);
      var sz = SIZE * (0.8 + ((pulse + 1) * 0.2));

      COLORS.forEach(function(col, i) {
        var nc = COLORS[(i+1) % COLORS.length];
        ctx.beginPath();
        ctx.strokeStyle = lerp(col, nc, (i + off) / COLORS.length);
        if (sets.length) ctx.moveTo(sets[0].x, sets[0].y + i * (sz - 1));
        sets.forEach(function(s, pi) { if (pi) ctx.lineTo(s.x, s.y + i * sz); });
        ctx.lineWidth = sz;
        ctx.stroke();
      });

      requestAnimationFrame(frame);
    }

    document.addEventListener('mousemove', function(e) {
      cur.x = e.clientX; cur.y = e.clientY;
      if (!initted) {
        initted = true;
        for (var i = 0; i < LENGTH; i++) pts.push({x: cur.x, y: cur.y});
      }
    });

    window.addEventListener('resize', resize);
    resize();
    frame();
  </script>
</body>
</html>

More Cursor Effects Animations