Skip to content

Instantly share code, notes, and snippets.

@SompalSingh
Created July 21, 2025 05:44
Show Gist options
  • Select an option

  • Save SompalSingh/7039905e8769e12229b3dd33e3f2091b to your computer and use it in GitHub Desktop.

Select an option

Save SompalSingh/7039905e8769e12229b3dd33e3f2091b to your computer and use it in GitHub Desktop.
Bunny Slider πŸ°πŸ’–
<div class="container">
<div class="track" id="track">
<div class="rabbit" id="rabbit">🐰</div>
<div class="carrot">πŸ₯•</div>
<div id="text">Slide to feed the hungry bunny & <br> watch the love bloom! πŸ’–</div>
</div>
</div>
const rabbit = document.getElementById("rabbit");
const track = document.getElementById("track");
const carrot = document.querySelector(".carrot");
let dragging = false;
let offsetX = 0;
let atEnd = false;
let lastSparkle = 0;
function getLimits() {
return {
min: 0,
max: track.offsetWidth - rabbit.offsetWidth
};
}
rabbit.addEventListener("mousedown", (e) => {
dragging = true;
offsetX = e.clientX - rabbit.getBoundingClientRect().left;
document.body.style.userSelect = "none";
});
document.addEventListener("mousemove", (e) => {
if (!dragging) return;
moveRabbit(e.clientX);
maybeSparkle();
});
document.addEventListener("mouseup", () => {
dragging = false;
document.body.style.userSelect = "";
});
rabbit.addEventListener("touchstart", (e) => {
dragging = true;
offsetX = e.touches[0].clientX - rabbit.getBoundingClientRect().left;
document.body.style.userSelect = "none";
});
document.addEventListener("touchmove", (e) => {
if (!dragging) return;
moveRabbit(e.touches[0].clientX);
maybeSparkle();
});
document.addEventListener("touchend", () => {
dragging = false;
document.body.style.userSelect = "";
});
function moveRabbit(clientX) {
const trackRect = track.getBoundingClientRect();
let x = clientX - trackRect.left - offsetX;
const { min, max } = getLimits();
x = Math.max(min, Math.min(max, x));
rabbit.style.left = x + "px";
if (x >= max) {
if (!atEnd) {
popHearts();
atEnd = true;
}
} else {
atEnd = false;
}
}
function popHearts() {
if (rabbit.classList.contains("popped")) return;
rabbit.classList.add("popped");
setTimeout(() => rabbit.classList.remove("popped"), 2000);
const rabbitRect = rabbit.getBoundingClientRect();
const heart = document.createElement("div");
heart.className = "heart";
heart.textContent = "πŸ’—";
heart.style.left = rabbitRect.left + rabbitRect.width / 2 - 32 + "px";
heart.style.top = rabbitRect.top - 40 + "px";
heart.style.position = "fixed";
document.body.appendChild(heart);
setTimeout(() => heart.remove(), 2000);
}
function maybeSparkle() {
const now = Date.now();
if (now - lastSparkle > 150) {
lastSparkle = now;
const rabbitRect = rabbit.getBoundingClientRect();
const sparkle = document.createElement("div");
sparkle.className = "sparkle";
sparkle.textContent = "✨";
const offset = (Math.random() - 0.5) * 24;
sparkle.style.left =
rabbitRect.left + rabbitRect.width / 2 + offset - 16 + "px";
sparkle.style.top = rabbitRect.top + 4 + "px";
sparkle.style.position = "fixed";
document.body.appendChild(sparkle);
setTimeout(() => sparkle.remove(), 1000);
}
}
body {
margin: 0;
background: linear-gradient(135deg, #f754b8 0%, #ffe4ec 100%);
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
overflow: hidden;
font-family: "Comic Sans MS", cursive;
}
.container {
position: relative;
width: 60%;
max-width: 350px;
height: 80px;
display: flex;
align-items: center;
justify-content: center;
}
.track {
position: relative;
width: 100%;
height: 12px;
background: #e95f88;
border-radius: 10px;
margin: 0;
top: 0;
transform: none;
display: flex;
align-items: center;
justify-content: center;
}
.rabbit {
position: absolute;
top: -15px;
left: -10px;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
font-size: 2rem;
transition: left 0.05s ease-out;
z-index: 2;
cursor: grab;
}
.rabbit:active {
cursor: grabbing;
}
.carrot {
position: absolute;
right: -8px;
top: -15px;
font-size: 1.5rem;
z-index: 1;
}
#text {
position: absolute;
top: 48px;
width: 100%;
text-align: center;
color: #e63c6f;
font-weight: bold;
pointer-events: none;
}
.heart,
.sparkle {
position: absolute;
font-size: 3rem;
animation: floatUp 2s ease-out forwards;
pointer-events: none;
}
.heart {
color: #f43193;
}
.sparkle {
color: #ffd700;
font-size: 2rem;
animation: floatUpSparkle 1s linear forwards;
}
@keyframes floatUp {
0% {
transform: translateY(0) scale(1);
opacity: 1;
}
100% {
transform: translateY(-100px) scale(1.5);
opacity: 0;
}
}
@keyframes floatUpSparkle {
0% {
transform: translateY(0) scale(1) rotate(0deg);
opacity: 1;
}
100% {
transform: translateY(-60px) scale(1.5) rotate(30deg);
opacity: 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment