<section class="demo" id="stage">
<div class="demo__goo" id="blobs"></div>
</section>.demo {
position: relative;
min-height: 100%;
height: 100%;
background: #08080a;
overflow: hidden;
}
.demo__goo {
position: absolute;
inset: 0;
filter: blur(14px) contrast(24);
background: #08080a;
}
.demo__blob {
position: absolute;
border-radius: 50%;
background: #f4f4f2;
margin: 0;
}const stage = document.querySelector("#blobs");
const COUNT = 5;
const blobs = [];
const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
for (let i = 0; i < COUNT; i += 1) {
const el = document.createElement("span");
el.className = "demo__blob";
const size = 52 - i * 6;
el.style.width = size + "px";
el.style.height = size + "px";
stage.appendChild(el);
blobs.push({
el: el,
x: window.innerWidth * 0.5,
y: window.innerHeight * 0.5,
});
}
const pointer = { x: window.innerWidth * 0.5, y: window.innerHeight * 0.45 };
document.querySelector("#stage").addEventListener("pointermove", function (event) {
pointer.x = event.clientX;
pointer.y = event.clientY;
});
function tick() {
blobs.forEach(function (blob, index) {
const lag = 0.2 - index * 0.03;
blob.x += (pointer.x - blob.x) * lag;
blob.y += (pointer.y - blob.y) * lag;
blob.el.style.transform = "translate(" + (blob.x - 26) + "px," + (blob.y - 26) + "px)";
});
if (!reduce) requestAnimationFrame(tick);
}
tick();