A Pen by Divyam Sharma on CodePen.
Created
July 21, 2025 05:44
-
-
Save SompalSingh/7039905e8769e12229b3dd33e3f2091b to your computer and use it in GitHub Desktop.
Bunny Slider π°π
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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