<div class="ball">
<div class="halo"></div>
<div class="halo"></div>
<div class="halo"></div>
</div>
:root {
--mouse-x;
--mouse-y;
--scale;
--radius: 40px;
--factor: 1;
}
.ball {
width: var(--radius);
height: var(--radius);
background: #D92659;
border-radius: 50%;
position:absolute;
/* use calc() and the CSS variables created above to center the ball around the mouse position. */
transform: translate(calc(var(--mouse-x) * 1px - var(--radius)/2),calc(var(--mouse-y) * 1px - var(--radius)/2));
}
.halo {
width: var(--radius);
height: var(--radius);
background: rgb(114, 61, 83);
border-radius: 50%;
position:absolute;
opacity: .15;
/* filter: blur(var(--factor)); */
transform: scale(calc(var(--scale) * var(--factor)));
}
.halo:nth-of-type(1) {
--factor: .3;
}
.halo:nth-of-type(2) {
--factor: 0.5;
}
.halo:nth-of-type(3) {
--factor: .9;
}
body {
background: #070611;
font-family: Verdana, sans-serif;
}
p {
color: whitesmoke;
width: 400px;
top: 10px;
left: 10px;
position:absolute;
}
var [xpos,targetX,ypos,targetY, velX, velY] = [0,0,0,0,0,0];
const docStyle = document.documentElement.style;
const drag = 0.8;
const strength = 0.12;
function springItOn() {
var diffX = targetX - xpos;
diffX *= strength;
velX *=drag;
velX += diffX;
xpos += velX;
var diffY = targetY - ypos;
diffY *= strength;
velY *=drag;
velY += diffY;
ypos += velY;
//apply the newly calculated positions via CSS custom properties each frame. SO FANCY
docStyle.setProperty('--mouse-x', xpos);
docStyle.setProperty('--mouse-y', ypos);
//set the halo scale property baesd on some arbitrary math for kicks
docStyle.setProperty('--scale', (velY + velX)*strength);
requestAnimationFrame(springItOn);
}
springItOn();
//update the target position based on where the mouse is
document.addEventListener('mousemove', (e) => {
targetX = e.clientX;
targetY = e.clientY;
});
View Compiled
This Pen doesn't use any external CSS resources.