Building a Timer Clock

Niraj Chaurasiya

03 June 2024

Table of Contents

Downloadable Assets

    For this project, we need to download two assets.

    The first one is the logo, and the second is the alarm sound. Download them in your root folder!

    Download alarm sound, here

    Download logo, here

Initializing a project

    Now, you have done downloading with the required assets from above.

    Its time to initialize a project.

    In the same folder where you download the both assets, make three files as index.html, index.css, index.js.

    Such that:

Structuring the site with HTML

    Now that we are done with downloading assets and initializing a project, lets create the structure with HTML.

    Firstly, go inside index.html file and write the basic HTML strucuture code.

      
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <link rel="stylesheet" href="index.css" />
        <link rel="shortcut icon" href="logo.png" type="image/x-icon" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Timer-App</title>
      </head>
      <body>
        
      </body>
      <script src="index.js"></script>
    </html>
    
                    

    In the above code, we also include index.css and index.js along with the logo.

    Now, we will create a div with class name, container with the heading inside the body. We also added two div as id clock and timer. The div with ID clock will be responsible for showing the current time.
    And, the div with ID timer will be responsible for fetching the time dynamically set by user and showing the timer in decreasing format.

      
    <div id="container">
        <h3 class="top-msg">Welcome to the Timer-App👋</h3>
        <div id="clock"></div>
        <div id="timer"></div>
    </div>
    
                    

    Now, we will add a div with class name dropdown after the div with ID timer. This will be responsible for all the actions that user can perform like setting up hours, minutes, and start a timer.

    The code looks like:

      
    <div class="dropdown">
        <label for="hours">Hours:</label>
            <select id="hours">
                <!-- Add hours dynamically -->
            </select>
    
        <label for="minutes">Minutes:</label>
            <select id="minutes">
                <!-- Add minutes dynamically -->
            </select>
    
        <button class="animated-button" id="startCustomTimerButton">
            <svg
              viewBox="0 0 24 24"
              class="arr-2"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z"
              ></path>
            </svg>
            <span class="text">Set Timer</span>
            <span class="circle"></span>
            <svg
              viewBox="0 0 24 24"
              class="arr-1"
              xmlns="http://www.w3.org/2000/svg"
            >
              <path
                d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z"
              ></path>
            </svg>
        </button>
    </div>
    
                    

    We are going to add hours and minutes options dynamically with JS.

    The final HTML codes look like:

      
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <link rel="stylesheet" href="index.css" />
        <link rel="shortcut icon" href="logo.png" type="image/x-icon" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Timer-App</title>
      </head>
      <body>
        <div id="container">
          <h3 class="top-msg">Welcome to the Timer-App👋</h3>
          <div id="clock"></div>
          <div id="timer"></div>
    
          <div class="dropdown">
            <label for="hours">Hours:</label>
            <select id="hours">
              <!-- Add hours dynamically -->
            </select>
    
            <label for="minutes">Minutes:</label>
            <select id="minutes">
              <!-- Add minutes dynamically -->
            </select>
    
            <button class="animated-button" id="startCustomTimerButton">
              <svg
                viewBox="0 0 24 24"
                class="arr-2"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z"
                ></path>
              </svg>
              <span class="text">Set Timer</span>
              <span class="circle"></span>
              <svg
                viewBox="0 0 24 24"
                class="arr-1"
                xmlns="http://www.w3.org/2000/svg"
              >
                <path
                  d="M16.1716 10.9999L10.8076 5.63589L12.2218 4.22168L20 11.9999L12.2218 19.778L10.8076 18.3638L16.1716 12.9999H4V10.9999H16.1716Z"
                ></path>
              </svg>
            </button>
          </div>
        </div>
      </body>
      <script src="index.js"></script>
    </html>
                    

Styling with CSS

    CSS codes are simple to understand, so I will not explain those. I will provide you with the code directly.

    Below is the all CSS codes.

      
    body {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
        background-color: rgb(0, 0, 0);
        color: white;
        font-family: Arial, sans-serif;
      }
      
      #container {
        background-color: #0d0d0c;
        width: 80vw;
        margin: auto;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        min-height: 100vh;
        box-shadow: rgba(50, 51, 50, 0.888) 0px 7px 29px 0px;
      }
      
      #clock,
      #timer {
        text-align: center;
        font-size: 100px;
      }
      
      @media (max-width: 1000px) {
        #clock,
        #timer {
          text-align: center;
          font-size: 80px;
        }
      }
      
      @media (max-width: 815px) {
        #clock,
        #timer {
          text-align: center;
          font-size: 60px;
        }
      }
      
      @media (max-width: 610px) {
        #clock,
        #timer {
          text-align: center;
          font-size: 40px;
        }
      }
      
      @media (max-width: 560px) {
        #clock,
        #timer {
          text-align: center;
          font-size: 30px;
        }
        .dropdown {
          display: flex;
          flex-direction: column;
          gap: 20px;
          align-items: center;
          margin-top: 20px;
        }
        select {
          padding: 10px 40px !important;
          border: 2px solid rgb(255, 255, 255);
          border-radius: 10px;
          background-color: white;
          color: black;
          margin-right: 10px;
        }
        .message-sign {
          color: rgb(253, 192, 202);
          text-shadow: 1px 1px 0 rgb(236, 159, 172) !important;
        }
        .message-sign span {
          color: rgb(104, 173, 252);
          text-shadow: 1px 1px 0 rgb(81, 135, 160) !important;
        }
        .time-sign {
          color: rgb(215, 146, 194);
          text-shadow: 1px 1px 0 rgb(160, 81, 81) !important;
        }
        .dropdown {
          text-shadow: 2px 2px 0 rgb(100, 97, 97);
        }
      }
      
      #clock span,
      #timer span {
        font-weight: 800;
      }
      
      .animated-button {
        position: relative;
        display: flex;
        align-items: center;
        gap: 4px;
        padding: 10px 36px;
        border: 4px solid;
        border-color: transparent;
        font-size: 16px;
        background-color: inherit;
        border-radius: 100px;
        font-weight: 600;
        color: #44d52a;
        box-shadow: 0 0 0 2px #44d52a;
        cursor: pointer;
        overflow: hidden;
        transition: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
      }
      
      .animated-button svg {
        position: absolute;
        width: 24px;
        fill: #44d52a;
        z-index: 9;
        transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
      }
      
      .animated-button .arr-1 {
        right: 16px;
      }
      
      .animated-button .arr-2 {
        left: -25%;
      }
      
      .animated-button .circle {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 20px;
        height: 20px;
        background-color: #44d52a;
        border-radius: 50%;
        opacity: 0;
        transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
      }
      
      .animated-button .text {
        position: relative;
        z-index: 1;
        transform: translateX(-12px);
        transition: all 0.8s cubic-bezier(0.23, 1, 0.32, 1);
      }
      
      .animated-button:hover {
        box-shadow: 0 0 0 12px transparent;
        color: #212121;
        border-radius: 12px;
      }
      
      .animated-button:hover .arr-1 {
        right: -25%;
      }
      
      .animated-button:hover .arr-2 {
        left: 16px;
      }
      
      .animated-button:hover .text {
        transform: translateX(12px);
      }
      
      .animated-button:hover svg {
        fill: #212121;
      }
      
      .animated-button:active {
        scale: 0.95;
        box-shadow: 0 0 0 4px #44d52a;
      }
      
      .animated-button:hover .circle {
        width: 220px;
        height: 220px;
        opacity: 1;
      }
      
      .dropdown {
        display: flex;
        align-items: center;
        margin-top: 20px;
      }
      
      label {
        margin-right: 5px;
        font-size: 1em;
        color: white;
      }
      
      select {
        padding: 10px;
        border: 2px solid rgb(255, 255, 255);
        border-radius: 10px;
        background-color: white;
        color: black;
        margin-right: 10px;
      }
      
      button.startCustomTimer {
        padding: 10px 20px;
        border-radius: 20px;
      }
      .message-sign {
        color: rgb(253, 192, 202);
        text-shadow: 4px 2px 0 rgb(236, 159, 172);
      }
      .message-sign span {
        color: rgb(104, 173, 252);
        text-shadow: 4px 2px 0 rgb(81, 135, 160);
      }
      .time-sign {
        color: rgb(215, 146, 194);
        text-shadow: 4px 2px 0 rgb(160, 81, 81);
      }
      .dropdown {
        text-shadow: 2px 2px 0 rgb(100, 97, 97);
      }
      
      .top-msg {
        font-size: 30px;
        color: #44d52a;
        text-align: center;
      }
    

Adding logic with JS!

    To understand the JS codes in-depth, please watch the video embeded below.

    For now, I will write all the JS code together!

    
      const hours = document.querySelector("#hours");
      const startCustomTimerButton = document.querySelector(
        "#startCustomTimerButton"
      );
      
      function startCustomTimer() {
        // Get the selected values from the dropdowns
        const selectedHours = document.querySelector("#hours").value;
        const selectedMinutes = document.querySelector("#minutes").value * 5;
        console.log(selectedHours);
        console.log(selectedMinutes);
        // Convert hours and minutes to seconds
        const durationInSeconds = selectedHours * 3600 + selectedMinutes * 60;
      
        // Start the custom timer
        startTimer(durationInSeconds);
      }
      
      startCustomTimerButton.addEventListener("click", startCustomTimer);
      
      const optionsHTML = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 15, 20, 24]
        .map(
          (e) => `
        <option key="${e}" value="${e}">
          ${e.toString().padStart(2, "0")}
        </option>
      `
        )
        .join("");
      
      hours.insertAdjacentHTML("afterbegin", optionsHTML);
      
      const minutes = document.querySelector("#minutes");
      
      const minutesOptionsHTML = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
        .map(
          (e) => `
        <option key="${e}" value="${e}">
          ${e * (5).toString().padStart(2, "0")}
        </option>
      `
        )
        .join("");
      
      minutes.insertAdjacentHTML("afterbegin", minutesOptionsHTML);
      
      const timer = document.querySelector("#timer");
      const clock = document.querySelector("#clock");
      let currentTimerId; // Store the current timer ID
      
      function updateClock() {
        const getTime = new Date();
        let hours =
          getTime.getHours() >= 10 ? getTime.getHours() : getTime.getHours();
        let minutes =
          getTime.getMinutes() >= 10
            ? getTime.getMinutes()
            : "0" + getTime.getMinutes();
        let seconds =
          getTime.getSeconds() >= 10
            ? getTime.getSeconds()
            : "0" + getTime.getSeconds();
        let formatHours = hours > 12 ? hours - 12 : hours;
        formatHours = formatHours >= 10 ? formatHours : "0" + formatHours;
        let isAM_PM = hours > 12 ? "PM" : "AM";
        let timeInMinutesAndSeconds =
          formatHours + `:` + minutes + `:` + seconds + ` ` + isAM_PM;
      
        // Update the content of the #clock element
        clock.innerHTML = `<span class="time-sign">${timeInMinutesAndSeconds}</span>`;
      }
      
      // Initial call to update the clock
      updateClock();
      
      setInterval(updateClock, 1000);
      
      // timer
      function startTimer(durationInSeconds) {
        // Clear the previous timer content
        timer.innerHTML = "";
      
        let timeRemaining = durationInSeconds;
      
        function updateTimer() {
          const hr =
            Math.floor(timeRemaining / 3600) > 9
              ? Math.floor(timeRemaining / 3600)
              : "0" + Math.floor(timeRemaining / 3600);
      
          let minutes = Math.floor((timeRemaining % 3600) / 60);
          const seconds =
            timeRemaining % 60 < 10 ? "0" + (timeRemaining % 60) : timeRemaining % 60;
      
          timer.innerHTML = timeRemaining
            ? `<span>${hr}:${
                minutes < 10 ? `0${minutes}` : minutes
              }:${seconds}</span>`
            : `<span class="message-sign">Select  <span>a timer</span> </span>`;
      
          if (timeRemaining > 0) {
            timeRemaining--;
            currentTimerId = setTimeout(updateTimer, 1000);
          } else {
            playAlarm();
          }
        }
      
        // Clear the previous timer if it exists
        if (currentTimerId) {
          clearTimeout(currentTimerId);
        }
      
        updateTimer();
      }
      
      startTimer();
      
      function playAlarm() {
        const alarm = new Audio("alarm.mp3");
        alarm.play();
      }
        

I hope you have gain a solid understanding on making a timer app from scratch.

Follow me on X: https://twitter.com/@loveforrobotics

My YouTube channel link where I share amazing videos like this: https://youtube.com/@niraj.chaurasiya

Video on this project

Tags

html

css

js

timer-app