library / backgrounds / 3-ascendant-light
live - 60fps 1920 x 1080
3-ascendant-light.html - self-contained
<!DOCTYPE html>
<html>
<head>
<title>3. Ascendant Light</title>
<style>
    body {
        margin: 0;
        height: 100vh;
        background-color: #1a1a2e;
        overflow: hidden;
        position: relative;
    }

    .light-source {
        position: absolute;
        top: -20%;
        left: 50%;
        width: 300%;
        height: 150%;
        transform: translateX(-50%);
        background: linear-gradient(
            45deg,
            rgba(255, 238, 204, 0) 40%,
            rgba(255, 238, 204, 0.25) 48%,
            rgba(255, 238, 204, 0.25) 52%,
            rgba(255, 238, 204, 0) 60%
        );
        animation: pan-light 10s infinite linear;
        /* To create a soft origin point for the rays */
        -webkit-mask-image: radial-gradient(ellipse at 50% -20%, black 20%, transparent 70%);
        mask-image: radial-gradient(ellipse at 50% -20%, black 20%, transparent 70%);
    }

    .light-source.two {
        transform: translateX(-50%) rotate(-20deg);
        animation-duration: 8s; /* Vary speed for realism */
    }

    @keyframes pan-light {
        from { transform: translateX(-50%) rotate(-40deg); }
        to { transform: translateX(-50%) rotate(40deg); }
    }

    .mote-container {
        position: absolute;
        top: 0; left: 0;
        width: 100%;
        height: 100%;
    }
    
    .mote {
        position: absolute;
        width: 4px;
        height: 4px;
        background: #fff;
        border-radius: 50%;
        opacity: 0.5;
        box-shadow: 0 0 10px #ffeecc;
        animation: float 10s infinite linear;
    }
    
    @keyframes float {
        0% { 
            transform: translateY(110vh) translateX(0) rotate(0deg); 
            opacity: 0;
        }
        10% { opacity: 0.7; }
        90% { opacity: 0.7; }
        100% {
            transform: translateY(-10vh) translateX(100px) rotate(360deg);
            opacity: 0;
        }
    }
</style>
</head>
<body>

<div class="light-source"></div>
<div class="light-source two"></div>

<div class="mote-container" id="moteContainer"></div>

<script>
    const container = document.getElementById('moteContainer');
    const numMotes = 50;

    for (let i = 0; i < numMotes; i++) {
        const mote = document.createElement('div');
        mote.className = 'mote';
        
        const size = Math.random() * 3 + 1;
        mote.style.width = `${size}px`;
        mote.style.height = `${size}px`;
        
        mote.style.left = `${Math.random() * 100}vw`;
        mote.style.animationDelay = `${Math.random() * -10}s`;
        mote.style.animationDuration = `${Math.random() * 5 + 8}s`;
        
        container.appendChild(mote);
    }
</script>


<script>
  /**
   * Animation control function, called on every frame.
   * @param {object} frame - The animation frame object (contains time, progress, etc.).
   */
  window.nextFrame = function(frame) {
    // AI-suggested functions to consider for this animation:
    // - document.querySelectorAll\n    // - element.style.transform\n    // - element.style.opacity\n    // - Math.sin\n    // - Math.cos\n    // - performance.now\n    // - Math.random\n    // - element.style.animationDuration\n    // - element.style.animationPlayState\n    // - element.animate\n    // - container.appendChild\n    // - element.remove

    // Add your animation logic here.
    // console.log('Current frame progress:', frame.progress);
    
    // Bridge to existing animation if any.
    if (typeof animate === 'function') {
      animate(frame.time);
    }
  }

  // If there's an existing animation loop, we can modify it to be controlled by nextFrame.
  // This is a placeholder for how you might adapt your code.
  if (typeof requestAnimationFrame === 'function' && !window.__HTV__?.exporting) {
    let tick = 0;
    function animate(time) {
      // Your animation logic driven by RAF.
      tick++;
      // draw(tick);
      requestAnimationFrame(animate);
    }
    // requestAnimationFrame(animate);
  }
</script>
</body>
</html>

About this animation

Rising beams of ethereal light.

Under the hood

SVG Gradient Flow

Built on optimized SVG markup, this animation transitions between multiple linear and radial gradients. SVG properties are extremely scalable, ensuring the light blooms remain perfectly crisp on high-DPI retina displays without inflating file sizes.

Source Code
Source copied
Partner hosting options for the copied effect:
Vercel Netlify Hostinger