ROB'S GARAGE DESIGN STUDIO
CSS3 NEON RAINBOW MOUSE TRAIL
Web Page Code Highlights
• CSS and Javascript for Neon Rainbow Bubbles Mouse Trail. No Dependencies.
• FX Effects: Rainbow Color Changing Mouse Trail Bubbles with Explosive on-Click Particles.
This web page Validates at:
Neon Rainbow Mouse Trail Javascript
Creating a mouse trail effect primarily involves JavaScript to track mouse movement and dynamically add/remove image elements, with CSS used for styling and animation of these images.
Explanation:
• HTML:
A container div is used to hold the dynamically created trail images.
CSS:
• mouse-trail-container: Fixed positioning ensures the container overlays the viewport and pointer-events: none prevents the trail images from blocking clicks or scrolling.
trail-image: Images are absolutely positioned and initially hidden (opacity: 0, transform: scale(0)). A transition property provides smooth fading and scaling effects.
trail-image.active: This class is added by JavaScript to trigger the fade-in and scale-up animation.
JavaScript:
• An event listener on mousemove triggers creation of a new img element (throttled). The image's position is calculated relative to the overlay container using getBoundingClientRect + clientX/clientY. A small requestAnimationFrame-based throttle reduces DOM churn. Images are removed after their transition completes.
Customization:
• Particle Size: Adjust the random size range in the createParticle() function.
• Color Cycling: Modify the global hue incrementation to speed up or slow down rainbow shifting.
• Trail Density: Change spawnDistance to increase or reduce how many particles follow the mouse.
• Explosion Intensity: Adjust the amount, range, and duration of particles inside the click handler.
• Comet Effect: Enable/disable or modify the chained mini-particles created when comet: true is used.
document.addEventListener("DOMContentLoaded", () => {
const container = document.querySelector(".mouse-trail-container");
let hue = 0;
let lastX = 0, lastY = 0;
const spawnDistance = 12; // smaller distance for ultra dense trail
function createParticle(x, y, options = {}) {
const p = document.createElement("div");
p.className = "particle";
const size = options.size || Math.random() * 8 + 4;
p.style.width = `${size}px`;
p.style.height = `${size}px`;
p.style.left = `${x}px`;
p.style.top = `${y}px`;
const pHue = (hue + (options.offsetHue || 0)) % 360;
p.style.color = `hsl(${pHue}, 100%, 60%)`;
container.appendChild(p);
// Physics-like drift
const velocityX = ((Math.random() - 0.5) * (options.range || 100));
const velocityY = ((Math.random() - 0.5) * (options.range || 100));
const rotate = (Math.random() - 0.5) * 720;
const scale = 0.3 + Math.random();
const anim = p.animate([
{ transform: `translate(0,0) rotate(0deg) scale(1)`, opacity: 1 },
{ transform: `translate(${velocityX}px, ${velocityY}px) rotate(${rotate}deg) scale(${scale})`, opacity: 0 }
], {
duration: (options.duration || 1200) + Math.random() * 800,
easing: 'cubic-bezier(0.22, 1, 0.36, 1)'
});
anim.onfinish = () => p.remove();
// Optional comet chain
if(options.comet){
const chainCount = 2 + Math.floor(Math.random()*3);
for(let i=0; i<chainCount; i++){
setTimeout(() => {
createParticle(x + velocityX*0.3, y + velocityY*0.3, {
size: size*0.6,
range: options.range*0.6,
duration: options.duration*0.6,
offsetHue: Math.random()*30
});
}, i*50);
}
}
}
window.addEventListener("mousemove", e => {
const dx = e.clientX - lastX;
const dy = e.clientY - lastY;
const dist = Math.sqrt(dx*dx + dy*dy);
if(dist > spawnDistance){
hue = (hue + 1) % 360;
// Main particle with comet
createParticle(e.clientX, e.clientY, { comet: true });
lastX = e.clientX;
lastY = e.clientY;
}
});
window.addEventListener("click", e => {
const x = e.clientX;
const y = e.clientY;
const explosionParticles = 60 + Math.floor(Math.random()*40);
for(let i=0; i<explosionParticles; i++){
createParticle(x, y, {
range: 150 + Math.random()*150,
duration: 1500 + Math.random()*1200,
offsetHue: Math.random()*360
});
}
});
});