Close Menu

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    How to create Nike Shoes Animation using HTML CSS and JS

    8 April 2026

    How to Make Animated Login Form in HTML and CSS

    4 April 2026

    How to create Creepy Eye Button using HTML CSS and JS

    3 April 2026
    Facebook X (Twitter) Instagram YouTube Telegram Threads
    Coding StellaCoding Stella
    • Home
    • Blog
    • HTML & CSS
      • Login Form
    • JavaScript
    • Hire us!
    Coding StellaCoding Stella
    Home - JavaScript - How to create Creepy Eye Button using HTML CSS and JS
    JavaScript

    How to create Creepy Eye Button using HTML CSS and JS

    Coding StellaBy Coding Stella3 April 2026No Comments6 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Email WhatsApp Copy Link

    Let’s create a Creepy Eye Button using HTML, CSS, and JavaScript, where a simple button transforms into an interactive UI element that follows your cursor with animated blinking eyes, making it fun and visually engaging.

    We’ll use:

    • HTML to structure the button, including elements for the button itself, its cover, and the eyes (with pupils) so everything is layered properly for animation.
    • CSS to design the creepy look using custom colors, rounded shapes, and smooth transitions, along with keyframe animations to create the blinking effect and hover interactions for a lively feel.
    • JavaScript to add interactivity by tracking mouse or touch movement, calculating cursor position relative to the eyes, and dynamically moving the pupils using transforms so the button appears to “watch” the user in real time.

    This project is perfect for learning how to combine creative UI design, animations, and interactive logic to build unique components that stand out in modern web design 👁️✨

    HTML :

    This is a basic HTML setup for a webpage: it defines the document type and language, sets important meta tags like character encoding and responsive viewport, gives the page a title, loads a custom font from Bunny Fonts, and links an external CSS file for styling; inside the body it has a div with id “root” which is likely used by JavaScript to render content, and finally it loads a JavaScript module (script.js) that controls the page’s functionality or animations (like the creepy eye button).

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <title>Creepy Eye Button | @coding.stella</title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
      <link rel='stylesheet' href='https://fonts.bunny.net/css?family=londrina-solid:400'>
      <link rel="stylesheet" href="./style.css">
    </head>
    
    <body>
      <div id="root"></div>
      <script type="module" src="./script.js"></script>
    
    </body>
    </html>

    CSS :

    This CSS resets default spacing and sets up global variables (colors, sizes, transitions), then styles the page to center everything with a dark background; it creates a “creepy button” with a colored cover, rounded shape, and smooth hover/press animations, while inside it small circular “eyes” with pupils are positioned and animated using keyframes to blink continuously, giving the button a creepy animated eye effect when you interact with it.

    * {
      border: 0;
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    :root {
      --hue: 223deg;
      --gray1: hsl(var(--hue) 10% 95%);
      --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;
      color-scheme: light dark;
      font-size: clamp(1.25rem, 1rem + 1.25vw, 2.5rem);
    }
    
    body,
    button {
      font: 1em/1.5 "Londrina Solid", sans-serif;
      transition: background-color var(--trans-dur), color var(--trans-dur);
    }
    
    body {
      background-color: light-dark(var(--gray1), var(--gray9));
      color: light-dark(var(--gray9), var(--gray1));
      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;
      outline: 0.1875em solid transparent;
      transition: outline 0.1s linear;
      -webkit-tap-highlight-color: transparent;
    }
    
    .creepy-btn,
    .creepy-btn__cover,
    .creepy-btn__eye {
      position: relative;
    }
    
    .creepy-btn,
    .creepy-btn__pupil {
      background-color: var(--black);
    }
    
    .creepy-btn__cover,
    .creepy-btn__pupil {
      border-radius: inherit;
      display: block;
    }
    
    .creepy-btn__cover {
      background-color: var(--primary5);
      box-shadow: 0 0 0 0.125em var(--black) inset;
      padding: 0.5em 1em;
      inset: 0;
      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__eye {
      animation: eye-blink 3s infinite;
      background-color: var(--gray1);
      border-radius: 50%;
      overflow: hidden;
      width: 0.75em;
      height: 0.75em;
    }
    
    .creepy-btn__eyes,
    .creepy-btn__pupil {
      position: absolute;
    }
    
    .creepy-btn__eyes {
      display: flex;
      align-items: center;
      gap: 0.375em;
      right: 1em;
      bottom: 0.5em;
      height: 0.75em;
    }
    
    .creepy-btn__pupil {
      aspect-ratio: 1;
      top: 50%;
      left: 50%;
      width: 0.375em;
      transform: translate(-50%, -50%);
    }
    
    .creepy-btn:focus-visible {
      outline: 0.1875em solid var(--primary3);
    }
    
    .creepy-btn:hover .creepy-btn__cover {
      background-color: var(--primary6);
    }
    
    .creepy-btn:focus-visible .creepy-btn__cover,
    .creepy-btn:hover .creepy-btn__cover {
      transform: rotate(-12deg);
      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);
    }
    
    @keyframes eye-blink {
    
      0%,
      92%,
      100% {
        animation-timing-function: cubic-bezier(0.32, 0, 0.67, 0);
        height: 0.75em;
      }
    
      96% {
        animation-timing-function: cubic-bezier(0.33, 1, 0.68, 1);
        height: 0;
      }
    }

    JavaScript:

    This React code creates a custom button component where two “eyes” follow your cursor: it uses useRef to track the eyes container position and useState to store pupil movement, then on mouse or touch move it calculates the angle and distance between the cursor and the eyes using math functions, converts that into x and y values, and applies a transform style so the pupils move inside the eyes, making it look like the button is watching your cursor while still behaving like a normal clickable button.

    import React, { StrictMode, useRef, useState } from "https://esm.sh/react";
    import { createRoot } from "https://esm.sh/react-dom/client";
    createRoot(document.getElementById("root")).render(React.createElement(StrictMode, null,
        React.createElement(CreepyButton, null, "Button")));
    function CreepyButton({ onClick, children }) {
        const eyesRef = useRef(null);
        const [eyeCoords, setEyeCoords] = useState({ x: 0, y: 0 });
        const translateX = `${-50 + eyeCoords.x * 50}%`;
        const translateY = `${-50 + eyeCoords.y * 50}%`;
        const eyeStyle = {
            "transform": `translate(${translateX}, ${translateY})`
        };
        const updateEyes = (e) => {
            var _a;
            const userEvent = "touches" in e ? e.touches[0] : e;
            // get the center of the eyes container and cursor location
            const eyesRect = (_a = eyesRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
            const eyes = {
                x: eyesRect.left + eyesRect.width / 2,
                y: eyesRect.top + eyesRect.height / 2
            };
            const cursor = {
                x: userEvent.clientX,
                y: userEvent.clientY
            };
            // calculate the eye angle
            const dx = cursor.x - eyes.x;
            const dy = cursor.y - eyes.y;
            const angle = Math.atan2(-dy, dx) + Math.PI / 2;
            // then the pupil distance from the eye center
            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;
            setEyeCoords({ x, y });
        };
        return (React.createElement("button", { className: "creepy-btn", type: "button", onClick: onClick, onMouseMove: updateEyes, onTouchMove: updateEyes },
            React.createElement("span", { className: "creepy-btn__eyes", ref: eyesRef },
                React.createElement("span", { className: "creepy-btn__eye" },
                    React.createElement("span", { className: "creepy-btn__pupil", style: eyeStyle })),
                React.createElement("span", { className: "creepy-btn__eye" },
                    React.createElement("span", { className: "creepy-btn__pupil", style: eyeStyle }))),
            React.createElement("span", { className: "creepy-btn__cover" }, children)));
    }

    In conclusion, this project shows how a simple portfolio can be transformed into a modern, interactive experience by combining HTML for structure, CSS for clean and responsive design, and JavaScript for animations and real-time interactions, helping you create a professional portfolio that not only showcases your work but also impresses users with smooth visuals and functionality 🚀

    If your project has problems, don’t worry. Just click to download the source code and face your coding challenges with excitement. Have fun coding!

    Animation JavaScript Web Development
    Share. Copy Link Twitter Facebook LinkedIn Email WhatsApp
    Previous ArticleHow to make 3D Flipping Pricing Card using HTML & CSS
    Next Article How to Make Animated Login Form in HTML and CSS
    Coding Stella
    • Website

    Related Posts

    JavaScript

    How to create Nike Shoes Animation using HTML CSS and JS

    8 April 2026
    JavaScript

    How to create Professional Developer Portfolio using HTML CSS and JS

    29 March 2026
    JavaScript

    How to create Archery Bullseye Game using HTML CSS and JS

    27 March 2026
    Add A Comment
    Leave A Reply Cancel Reply

    Trending Post

    Master Frontend in 100 Days Ebook

    2 March 202432K Views

    How to make Modern Login Form using HTML & CSS | Glassmorphism

    11 January 202431K Views

    How to make I love you Animation in HTML CSS & JavaScript

    14 February 202424K Views

    How to make Valentine’s Day Card using HTML & CSS

    13 February 202415K Views
    Follow Us
    • Instagram
    • Facebook
    • YouTube
    • Twitter
    ads
    Featured Post

    Best Programming Languages for Web Development

    25 January 2024

    How to create Airpods Animation using HTML CSS and JS

    15 July 2025

    How to Create Microsoft Homepage Clone in HTML CSS and Javascript

    12 December 2023

    How to make Animated Bouncy Clock in HTML CSS & JavaScript

    24 March 2025
    Latest Post

    How to create Nike Shoes Animation using HTML CSS and JS

    8 April 2026

    How to Make Animated Login Form in HTML and CSS

    4 April 2026

    How to create Creepy Eye Button using HTML CSS and JS

    3 April 2026

    How to make 3D Flipping Pricing Card using HTML & CSS

    31 March 2026
    Facebook X (Twitter) Instagram YouTube
    • About Us
    • Privacy Policy
    • Return and Refund Policy
    • Terms and Conditions
    • Contact Us
    • Buy me a coffee
    © 2026 Coding Stella. Made with 💙 by @coding.stella

    Type above and press Enter to search. Press Esc to cancel.

    Ad Blocker Enabled!
    Ad Blocker Enabled!
    Looks like you're using an ad blocker. We rely on advertising to help fund our site.
    Okay! I understood