Build a Web Application using HTML CSS & JavaScript – Workout Rounds Timer

Web Design

Learn how to create a count down timer using HTML CSS3 and JavaScript in order to create a Web Application that can time a workout session.

In this tutorial we will build a complete application using HTML5, CSS3 and JavaScript. This application is heavily based on JavaScript functional programing.

Audio Files

HTML Source Code:

  <i class="fas fa-heartbeat"></i>

    <!-- create 3 stopwatches -->
    <div class="workout-timer-container flex">
      <header class="flex">
        <h1 class="title">Workout Rounds Timer</h1>
        <div class="inputs-container">
          <div class="input-group flex">
            <label class="roundTime">Round length</label>
            <input type="number" id="roundTime" placeholder="minutes" />
          </div>
          <div class="input-group flex">
            <label class="restTime">Rest length</label>
            <input type="number" id="restTime" placeholder="minutes" />
          </div>

          <button class="btn" id="start" onclick="startTimer()">Start</button>
        </div>
        <h4>Set the duration of your Rounds and Rest Time</h4>

        <h2 id="start-countdown"></h2>
        <h2 id="theTime"></h2>
      </header>

      <!-- todo: Round Container -->
      <div class="rounds-container flex">
        <section class="group flex">
          <div class="round">Round 1</div>
          <span class="round-time" id="round_1"></span>
        </section>
        <section class="group flex">
          <div class="rest">Rest</div>
          <span class="rest-time" id="rest_1"></span>
        </section>
        <section class="group flex">
          <div class="round">Round 2</div>
          <span class="round-time" id="round_2"></span>
        </section>
        <section class="group flex">
          <div class="rest">Rest</div>
          <span class="rest-time" id="rest_2"></span>
        </section>
        <section class="group flex">
          <div class="round">Round 3</div>
          <span class="round-time" id="round_3"></span>
        </section>
      </div>
    </div>

    <!--Audio Alerts -->
    <audio id="alert10Sec" loop>
      <source src="/audio/Wood clack.mp3" />
    </audio>
    <audio id="alertStop" loop>
      <source src="/audio/StopRound.mp3" />
    </audio>
    <audio id="alertGo" loop>
      <source src="/audio/StartRoundBell.mp3" />
    </audio>

CSS Source Code:

:root {
  --bg-c-1: #484c67;
  --bg-c-2: #37394e;
  --orange: #e98850;
  --red: #e24379;
  --blue: #01567d;
  --green: #44de00;
}

body {
  height: 100vh;
  margin: auto;
  color: #eee;
  text-shadow: 4px 4px 5px #333;
  background-color: var(--bg-c-1);
  position: relative;
}
.flex {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.workout-timer-container {
  width: 600px;
}

.title {
  font-size: 6rem;
  text-align: center;
  margin: 15vh 0;
}

h4 {
  text-align: center;
}

.inputs-container {
  display: flex;
  justify-content: center;
  width: 100%;
  background-color: var(--bg-c-2);
  padding: 1rem;
  border-radius: 5px;
  box-shadow: 0 15px 10px #333;
  transition: all 0.2s ease;
}
.inputs-container:hover {
  box-shadow: 0 10px 5px #333;
  transition: all 0.2s ease;
}
.input-group {
  padding: 1rem;
}
label.roundTime {
  font-size: 1.1rem;
  color: var(--red);
}
label.restTime {
  font-size: 1.1rem;
  color: var(--orange);
}
input {
  color: var(--orange);

  font-size: 2rem !important;
  max-width: 120px;
  text-align: center;
}
input::placeholder {
  color: #999;
}
input#roundTime {
  color: var(--red);
}
input#roundTime:hover {
  border-bottom: 1px solid var(--red);
}
input#restTime:hover {
  border-bottom: 1px solid var(--orange);
}

.btn {
  height: 100px;
  width: 100px;
  border-radius: 50%;
  background-color: var(--green);
  color: var(--bg-c-1);
  font-size: 1.4rem;
  font-weight: 500;
  box-shadow: 0 15px 10px #333;
  border: 2px solid #333;
}
.btn:active {
  transform: scale(0.95);
}
#theTime {
  background-color: var(--bg-c-2);
  border-radius: 5px;
  padding: 1rem;
  box-shadow: inset 0 0 15px 3px #333;
  color: var(--green);
}
.fas {
  font-size: 20rem;
  position: absolute;

  top: 10vh;
  z-index: -1;
  color: var(--red);
}
.fa-heartbeat {
  color: var(--red);
}
.fa-fist-raised {
  color: var(--orange);
}
.fa-chair {
  color: var(--green);
}
.group {
  height: 100vh;
  justify-content: space-evenly;
}
.group {
  display: none;
}
.active {
  font-size: 30vh;
  display: flex;
}

.active > .round,
.active > .rest {
  font-size: 10vh;
}

.round-time,
.rest-time {
  background-color: var(--bg-c-2);
  border-radius: 5px;
  box-shadow: 0 15px 10px #333;
  transition: all 0.2s ease;
}

/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}

/* Firefox */
input[type="number"] {
  -moz-appearance: textfield;
}

.animateSeconds {
  color: var(--red);
  animation: animateTime 1s ease;
}

@keyframes animateTime {
  from {
    opacity: 1;
    transform: scale(0);
  }
  to {
    opacity: 0;
    transform: scale(1);
  }
}

JS Code:

Down below you will find the javascript code for the countdown timer video. I will strongly encourage you to also follow along with the video in order to understand my thot process better.

{
  const myTime = setInterval(myTimer, 1000);
  function myTimer() {
    const today = new Date();
    const displayTime = today.toLocaleTimeString();
    document.getElementById("displayTime").innerHTML = displayTime;
  }
}
// todo: Get Elements from the DOM

const body = document.querySelector("body");
const icon = document.querySelector("i");

// ! get inputs.

const roundTimeInput = document.getElementById("roundTime");
const restTimeInput = document.getElementById("restTime");
const startStopBtn = document.getElementById("start");

// ! get Rounds and Rests
const round1 = document.getElementById("round_1");
const rest1 = document.getElementById("rest_1");
const round2 = document.getElementById("round_2");
const rest2 = document.getElementById("rest_2");
const round3 = document.getElementById("round_3");

// ! Get Alerts
const alert10sec = document.getElementById("alert10sec");
const alertStart = document.getElementById("alertStart");
const alertStop = document.getElementById("alertStop");

const startTimer = () => {
  // todo: Time stemps

  let roundTime = roundTimeInput.value * 60;
  let restTime = restTimeInput.value * 60;
  let time = "10";

  //  todo: Verification

  if (roundTimeInput.value === "" || restTimeInput.value === "") {
    alert("Input Round & Rest Time!");
    return;
  } else {
    // console.log("start");
    //todo: Stop count down
    startStopBtn.innerHTML = "Stop";
    startStopBtn.style.backgroundColor = "#e24379";
    startStopBtn.onclick = newWorkout;

    // todo: alert 10 sec

    setAlert(alert10sec);

    // todo: Start The Countdown
    const startCountdown = document.querySelector(".title");
    setInterval(() => {
      getReady(startCountdown);
    }, 1000);

    // todo: Start Workout
    setTimeout(() => {
      // todo: hide header
      document.querySelector("header").style.display = "none";

      // todo: alert Start Round
      setAlert(alertStart);

      // todo: Start First Round
      setInterval(() => {
        if (round1.innerText !== "0:00") {
          //   console.log("Round 1");
          //   ! Update Round
          updateRound(round1);
          round1.parentElement.classList.add("active");
          //   ! Change Icon
          addRemoveIconClass("fa-heartbeat", "fa-fist-raised");

          //   ! Alert 10 sec
          checkFor10Sec(round1);
          // !Alert Stop

          round1.innerText === "0:00" ? setAlert(alertStop) : round1;
        } else if (round1.innerText === "0:00" && rest1.innerText !== "0:00") {
          //todo: start rest 1
          // ! Toggle Display
          addRemoveActiveClass(round1, rest1);
          //   ! Update Rest
          updateRest(rest1);
          //   ! Change Icon
          addRemoveIconClass("fa-fist-raised", "fa-chair");
          //   ! Alert 10 sec

          checkFor10Sec(rest1);
          // !Alert Start next Round

          rest1.innerText === "0:00" ? setAlert(alertStart) : rest1;

          //   ! Rest Round Time
          resetRoundTime();
        } else if (rest1.innerText === "0:00" && round2.innerText !== "0:00") {
          //todo: start Round 2
          // ! Toggle Display
          addRemoveActiveClass(rest1, round2);
          //   ! Update Rest
          updateRound(round2);
          //   ! Change Icon
          addRemoveIconClass("fa-chair", "fa-fist-raised");
          //   ! Alert 10 sec

          checkFor10Sec(round2);
          // !Alert Stop Round

          round2.innerText === "0:00" ? setAlert(alertStop) : round2;

          //   ! Rest Round Time
          resetRestTime();
        } else if (round2.innerText === "0:00" && rest2.innerText !== "0:00") {
          //todo: start Rest 2
          // ! Toggle Display
          addRemoveActiveClass(round2, rest2);
          //   ! Update Rest
          updateRest(rest2);
          //   ! Change Icon
          addRemoveIconClass("fa-fist-raised", "fa-chair");
          //   ! Alert 10 sec

          checkFor10Sec(rest2);
          // !Alert Start next Round

          rest2.innerText === "0:00" ? setAlert(alertStart) : rest2;

          //   ! Rest Round Time
          resetRoundTime();
        } else if (round3.innerText !== "0:00") {
          //todo: start Round 3
          // ! Toggle Display
          addRemoveActiveClass(rest2, round3);
          //   ! Update Rest
          updateRound(round3);
          //   ! Change Icon
          addRemoveIconClass("fa-chair", "fa-fist-raised");
          //   ! Alert 10 sec

          checkFor10Sec(round3);
          // !Alert Stop  Round

          round3.innerText === "0:00" ? setAlert(alertStop) : round3;
        }
        // todo: Stop Workout and Create New Workout

        if (round3.innerText === "0:00") {
          body.innerHTML = `
            <h1 class="title" >Done</h1>
            <div class="inputs-container">
              <button class="btn" onclick="newWorkout()">Again</button>
            </div>  
            `;
        }
      }, 1000);
    }, 11000);

    // ! Check for 10 secondes Marker

    function checkFor10Sec(activity) {
      activity.innerText === "0:10"
        ? (setAlert(alert10sec), (activity.style.color = "#e24379"))
        : activity;
    }

    // ! Create addRemoveIconClass() function

    function addRemoveIconClass(currentIcon, nextIcon) {
      icon.classList.remove(currentIcon);
      icon.classList.add(nextIcon);
    }

    function addRemoveActiveClass(previousActivity, currentActivity) {
      previousActivity.parentElement.classList.remove("active");
      currentActivity.parentElement.classList.add("active");
    }

    //! Create Rounds and Rest Updates functions
    //* Rounds
    function updateRound(round) {
      const minutes = Math.floor(roundTime / 60);
      let seconds = roundTime % 60;

      seconds = seconds < 10 ? "0" + seconds : seconds;
      round.innerHTML = `${minutes}:${seconds}`;
      roundTime--;
    }
    function resetRoundTime() {
      return (roundTime = roundTimeInput.value * 60);
    }
    //* Rest
    function updateRest(rest) {
      const minutes = Math.floor(restTime / 60);
      let seconds = restTime % 60;

      seconds = seconds < 10 ? "0" + seconds : seconds;
      rest.innerHTML = `${minutes}:${seconds}`;
      restTime--;
    }
    function resetRestTime() {
      return (restTime = restTimeInput.value * 60);
    }
    // ! Create Countdown Function

    function getReady(element) {
      let seconds = time % 60;
      element.innerHTML = `
    <div class="inputs-container flex">
      <h4 class='title'>Get Ready in</h4>
      <h2 id='seconds' class='active animateSeconds'>${seconds}</h2>
     </div>
    `;

      time--;
    }

    // ! Interaction Alerts

    function setAlert(alert) {
      alert.play();
      setTimeout(() => {
        alert.pause();
        alert.currentTime = 0;
      }, 1300);
    }
  }
};

// ! Utility Function

// todo: Stop and Restart the App

const newWorkout = () => {
  window.location.reload();
};

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.