Untitled fiddle
by Tan
HTML
<div id="container" class="container">
<div id="grad1" class="grad1"></div>
<div id="grad2" class="grad2"></div>
<div id="grad3" class="grad3"></div>
<div id="grad4" class="grad4"></div>
</div>
CSS
.container {max-width:900px;height:500px;margin:auto;position:relative;overflow:hidden;border:1px solid #bbbbbb;}
.grad1, .grad2, .grad3, .grad4 {position:absolute;width:50%;height:50%;overflow:visible;border:1px solid #bbbbbb;}
.grad1 {top:-10%;left:-20%;
background: radial-gradient(50% 50% at center center, rgba(10, 149, 231, .12) 0, rgba(10, 149, 231, 0) 100%); }
.grad2 {top:20%;left:10%;
background: radial-gradient(50% 50% at center center, rgba(227,173,23,0.2) 0, rgba(227,173,23,0) 100%);}
.grad3 {top:50%;left:35%;
background: radial-gradient(50% 50% at center center, rgba(136, 85, 218, 0.1) 0, rgba(136, 85, 218,0) 100%);}
.grad4 {top:-15%;right:-15%;
background: radial-gradient(50% 50% at center center, rgba(57, 168, 63, 0.1) 0, rgba(57, 168, 63,0) 100%);}
JavaScript
(function() {
const container = document.getElementById('container');
const elements = ['grad1', 'grad2', 'grad3', 'grad4'].map(id => document.getElementById(id));
// Give each element its own independent motion parameters
const params = elements.map(() => ({
// random starting phase so they don't move in sync
angle1: Math.random() * Math.PI * 2,
angle2: Math.random() * Math.PI * 2,
// random speed for each axis
speed1: 0.0003 + Math.random() * 0.0004,
speed2: 0.0002 + Math.random() * 0.0005,
// how far it wanders, in % of container size
range1: 10 + Math.random() * 15,
range2: 10 + Math.random() * 15,
}));
// Capture each element's base top/left (from CSS) as the center point
const bases = elements.map(el => {
const style = getComputedStyle(el);
return {
top: parseFloat(style.top) || 0,
left: parseFloat(style.left) || 0,
right: style.right !== 'auto' ? parseFloat(style.right) : null,
};
});
function animate(time) {
elements.forEach((el, i) => {
const p = params[i];
const b = bases[i];
const offsetX = Math.sin(time * p.speed1 + p.angle1) * p.range1;
const offsetY = Math.cos(time * p.speed2 + p.angle2) * p.range2;
el.style.transform = `translate(${offsetX}%, ${offsetY}%)`;
});
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
})();