<div class="gooey-wrapper">
<div class="content-text">
<h1>Liquid Cursor</h1>
<p>Move your mouse around to see the gooey effect merge dynamically.</p>
</div>
<svg style="display: none;">
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" result="blur"></feGaussianBlur>
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 25 -10" result="goo"></feColorMatrix>
<feBlend in="SourceGraphic" in2="goo"></feBlend>
</filter>
</defs>
</svg>
<div class="cursor-container" id="cursor-container">
<!-- Blobs will be injected instantly by Javascript -->
</div>
</div>*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
margin: 0;
background: #fafafa;
min-height: 100vh;
overflow: hidden;
cursor: none;
}
.gooey-wrapper {
width: 100%;
height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.content-text {
text-align: center;
color: #111827;
z-index: 10;
pointer-events: none;
}
.content-text h1 {
font-size: clamp(3rem, 8vw, 5rem);
margin: 0 0 10px 0;
letter-spacing: -1px;
}
.content-text p {
font-size: 1.25rem;
color: #4b5563;
margin: 0;
}
.cursor-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 100;
filter: url("#goo");
}
.blob {
position: absolute;
border-radius: 50%;
background: #3b82f6;
transform: translate(-50%, -50%);
will-change: left, top, width, height;
}const container = document.getElementById("cursor-container");
const blobs = new Array();
const numBlobs = 6;
let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
window.addEventListener("mousemove", function(e) {
mouseX = e.clientX;
mouseY = e.clientY;
});
// Setup the trailing blobs
for (let i = 0; i < numBlobs; i++) {
const el = document.createElement("div");
el.className = "blob";
container.appendChild(el);
const blobObj = new Object();
blobObj.el = el;
blobObj.x = mouseX;
blobObj.y = mouseY;
const size = 60 - (i * 8);
el.style.width = size + "px";
el.style.height = size + "px";
blobs.push(blobObj);
}
function animateGoo() {
let targetX = mouseX;
let targetY = mouseY;
blobs.forEach(function(blobObj) {
// Interpolation makes the followers lag gently behind
blobObj.x += (targetX - blobObj.x) * 0.3;
blobObj.y += (targetY - blobObj.y) * 0.3;
blobObj.el.style.left = blobObj.x + "px";
blobObj.el.style.top = blobObj.y + "px";
targetX = blobObj.x;
targetY = blobObj.y;
});
window.requestAnimationFrame(animateGoo);
}
animateGoo();Nothing to show yetType HTML, CSS or JavaScript and your page appears here.
Click any element to find its code Esc
Check this code before you run it
It came from a shared link. It runs with fewer permissions, so it cannot open pop-ups, submit forms or start downloads.
0.00s / 0.00s
Nothing has animated yet. Hover, click or type in the preview and each CSS animation, transition or
element.animate() call shows up here as it plays.