Creepy Button
Home
Snippets
Creepy Button
HTML
CSS
JS
<div id="root"> <button class="creepy-btn"> <span class="creepy-btn__eyes"> <span class="creepy-btn__eye"> <span class="creepy-btn__pupil"></span> </span> <span class="creepy-btn__eye"> <span class="creepy-btn__pupil"></span> </span> </span> <span class="creepy-btn__cover">Button</span> </button> </div>
* { border: 0; box-sizing: border-box; margin: 0; padding: 0; } :root { --hue: 223deg; --gray1: hsl(var(--hue) 10% 90%); --gray9: hsl(var(--hue) 10% 15%); --black: hsl(0 0% 0%); --primary3: hsl(var(--hue) 90% 75%); --primary5: hsl(var(--hue) 90% 55%); --primary6: hsl(var(--hue) 90% 45%); --trans-dur: 0.3s; font-size: clamp(1.25rem, 1rem + 1.25vw, 2.5rem); } body { font: 1em / 1.5 "Londrina Solid", sans-serif; transition: background-color var(--trans-dur), color var(--trans-dur); background-color: var(--gray1); color: var(--gray9); display: grid; place-items: center; height: 100vh; } .creepy-btn { background-color: var(--black); border-radius: 1.25em; color: var(--gray1); cursor: pointer; letter-spacing: 1px; min-width: 9em; transition: outline 0.1s linear; -webkit-tap-highlight-color: transparent; position: relative; font-size: 1rem; } .creepy-btn__cover { background-color: var(--primary5); border-radius: inherit; display: block; padding: 0.5em 1em; inset: 0; position: relative; z-index: 999; transform-origin: 1.25em 50%; transition: background-color var(--trans-dur), transform var(--trans-dur) cubic-bezier(0.65,0,0.35,1); } .creepy-btn:hover .creepy-btn__cover { background-color: var(--primary6); } .creepy-btn:focus-visible { outline: 0.1875em solid var(--primary3); } .creepy-btn:focus-visible .creepy-btn__cover, .creepy-btn:hover .creepy-btn__cover { transform: rotate(-17deg); transition-timing-function: cubic-bezier(0.65,0,0.35,1.65); } .creepy-btn:active .creepy-btn__cover { transform: rotate(0); transition-timing-function: cubic-bezier(0.65,0,0.35,1); } .creepy-btn__eyes { position: absolute; right: 1em; bottom: 0.5em; display: flex; align-items: center; gap: 0.375em; height: 0.75em; z-index: 2; } .creepy-btn__eye { width: 0.75em; height: 0.75em; background-color: var(--gray1); border-radius: 50%; overflow: hidden; position: relative; animation: eye-blink 3s infinite; } .creepy-btn__pupil { width: 0.375em; aspect-ratio: 1; background-color: var(--black); border-radius: inherit; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); transition: transform 0.05s; } @keyframes eye-blink { 0%, 92%, 100% { height: 0.75em; } 96% { height: 0; } }
const button = document.querySelector(".creepy-btn"); const eyesRef = button.querySelector(".creepy-btn__eyes"); const pupils = button.querySelectorAll(".creepy-btn__pupil"); function updateEyes(e) { const event = e.touches ? e.touches[0] : e; const eyesRect = eyesRef.getBoundingClientRect(); const eyesCenter = { x: eyesRect.left + eyesRect.width / 2, y: eyesRect.top + eyesRect.height / 2 }; const dx = event.clientX - eyesCenter.x; const dy = event.clientY - eyesCenter.y; const angle = Math.atan2(-dy, dx) + Math.PI / 2; const visionRangeX = 180; const visionRangeY = 75; const distance = Math.hypot(dx, dy); const x = Math.sin(angle) * distance / visionRangeX; const y = Math.cos(angle) * distance / visionRangeY; pupils.forEach(pupil => { pupil.style.transform = `translate(${(-50 + x*50)}%, ${(-50 + y*50)}%)`; }); } button.addEventListener("mousemove", updateEyes); button.addEventListener("touchmove", updateEyes);
Ad #1
Ad #2
Scroll to Top