Make a Pomodoro Timer in JavaScript

Make a Pomodoro Timer in JavaScript
Code Snippet:Pomodoro Clock
Author: Julia Morozova
Published: January 20, 2024
Last Updated: January 22, 2024
Downloads: 1,128
License: MIT
Edit Code online: View on CodePen
Read More

This JavaScript code creates a Pomodoro Timer. It allows setting session and break times. The timer starts, pauses, and stops. The code dynamically updates the timer display and progress bar to track time intervals. It features buttons to adjust session and break times, providing a visual interface for time management. This timer follows the Pomodoro technique, aiding productivity by managing work and break intervals effectively.

It helps users manage their work time and break intervals efficiently, enhancing productivity and focus.

How to Make a Pomodoro Timer In JavaScript

1. Copy the HTML code provided into your HTML file. This code defines the structure of the Pomodoro Timer, including session and break settings, timer display, and control buttons.

<div class="container">
<!--   <h3>Pomodoro Clock</h3> -->
  <div class="circle total-progress">
    <div class="seconds progress">
      <div class="middle">
        <div id="time-status">
          <div id="timer-type"></div>
          <span class="hidden" id="hours-left"></span>
          <span id="min-left"></span>
          <span id="sec-left"></span>
        </div>
      </div>
    </div>
  </div>
  <div class="settings">
    <div class="session-settings">
      <span class="settings-headers">session time</span>
      <span id="session-time"></span>
      <button class="settings-btn-plus" id="session-plus" type="button">+</button>
      <button class="settings-btn-minus" id="session-minus" type="button">-</button>
    </div>
    <div class="break-settings">
      <span class="settings-headers">break time</span>
      <span id="break-time"></span>
      <button class="settings-btn-plus" id="break-plus" type="button">+</button>
      <button class="settings-btn-minus" id="break-minus" type="button">-</button>
    </div>
    <div class="operations">
      <button type="button" class="operation-btn" id="start">start</button>
<!--       <button type="button" class="operation-btn" id="pause">pause</button> -->
      <button type="button" class="operation-btn" id="stop">stop</button>
    </div>
  </div>
  <div class="footer">&copyjulsmorozova</div>
</div>

2. The CSS code styles the timer and provides a visually appealing design. You can customize the styles to match your website’s aesthetics.

* {
  box-sizing: border-box;
}

body {
  height: 100vh;
  width: 100%;
  margin: 0;
  display: flex;
  justify-content: center;
  font-family: Tahoma, Verdana, sans-serif;
  color: #777;
  background-color: #0E1826;
}

button {
  outline: none;
  border: none;
  min-width: 2rem;
  min-height: 2rem;
  background: none;
  color: #777;
  font-size: 1.7rem;
  margin: 0.3rem;
}
button:hover {
  color: #64D7DB;
}

.hidden {
  display: none;
}

.container {
  padding: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  align-items: center;
}

.circle {
  width: 15rem;
  height: 15rem;
  min-height: 15rem;
  background-color: #64D7DB;
  border: 0.125rem solid #b0b0b0;
  border-radius: 50%;
  margin: 2rem 0 1rem;
  color: #4097B2;
  font-size: 3rem;
  display: flex;
  position: relative;
  justify-content: center;
  align-items: center;
}
.circle.total-progress {
  background-image: linear-gradient(90deg, transparent 50%, #0E1826 50%), linear-gradient(90deg, #0E1826 50%, transparent 50%);
}
.circle .seconds {
  border-radius: 50%;
  background-color: #BFD7EA;
  width: 90%;
  height: 90%;
  display: flex;
  justify-content: center;
  align-items: center;
}
.circle .seconds.progress {
  background-image: linear-gradient(90deg, transparent 50%, #0E1826 50%), linear-gradient(90deg, #0E1826 50%, transparent 50%);
}

.middle {
  border-radius: 50%;
  background-color: #0E1826;
  width: 90%;
  height: 90%;
  display: flex;
  justify-content: center;
  align-items: center;
}

#time-status {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
}
#time-status #timer-type {
  width: 100%;
  text-align: center;
  margin: -1.3rem 0 0.5rem;
  font-size: 1.3rem;
  color: #777;
}

.settings {
  width: 60%;
  margin: 1rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}
.settings .session-settings, .settings .break-settings {
  width: 45%;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}
.settings .session-settings .settings-headers, .settings .session-settings #session-time, .settings .session-settings #break-time, .settings .break-settings .settings-headers, .settings .break-settings #session-time, .settings .break-settings #break-time {
  width: 100%;
  text-align: center;
  margin: 0.5rem;
}
.settings .session-settings #session-time, .settings .session-settings #break-time, .settings .break-settings #session-time, .settings .break-settings #break-time {
  font-size: 1.6rem;
  color: #4097B2;
}

.operations {
  margin: 1rem;
  width: 100%;
  display: flex;
  justify-content: center;
}
.operations button {
  margin: 0.5rem;
  width: 4rem;
  height: 2rem;
  line-height: 1.8rem;
  font-size: 0.9rem;
  color: #BFD7EA;
  background-color: #777;
}
.operations button:hover {
  opacity: 0.5;
}

.footer {
  height: 2rem;
  line-height: 2rem;
  width: 100%;
  display: flex;
  justify-content: flex-start;
  padding: 0 1.5rem;
  margin: 1rem 0 0;
}

3. Finally, add the following JavaScript code to your project. It manages session and break durations, controls the timer, and updates the display. You can explore the code to see how it works.

var increaseButtons = document.querySelectorAll('.settings-btn-plus');
var decreaseButtons = document.querySelectorAll('.settings-btn-minus');
var startBtn = document.querySelector("#start");
var stopBtn = document.querySelector("#stop");
var sessionTimeBlock = document.querySelector("#session-time");
var breakTimeBlock = document.querySelector("#break-time");
var timeStatusBlock = document.querySelector("#time-status");
var hoursSpan = document.querySelector("#hours-left");
var minSpan = document.querySelector("#min-left");
var secSpan = document.querySelector("#sec-left");
var timerTypeName = document.querySelector("#timer-type");
var totalProgress = document.querySelector(".total-progress");
var secondsProgress = document.querySelector(".progress");

var timer = '';//below used for setInterval/clearInterval
var timerActive = false;
var timerType = 'session';//is then changed to break
var startTime = 1500; //start of the session: session time by default
var sessionTime = 1500;//default session time stored in seconds
var breakTime = 300; //default break time stored in seconds;
var currentTime = 1500; //time displayed on timer in seconds

function displayDefaultTime() {
  sessionTimeBlock.innerHTML = displayMinutes(sessionTime) + ' min';
  breakTimeBlock.innerHTML = displayMinutes(breakTime) + ' min';
  displayCurrentTime();
}

function handleTotalProgress(startTime, currentTime) {
  var progressColor = '';
  if (timerType === 'session') {
      progressColor = '#64D7DB';
      totalProgress.style.backgroundColor = '#64D7DB';
    }
    else {
      progressColor = '#A75ACE';
      totalProgress.style.backgroundColor = '#A75ACE';
    }
  var timePassed = startTime - currentTime;
  var deg;
  if (timePassed < (startTime / 2)) {
    deg = 90 + (360 * timePassed / startTime)
    totalProgress.style.backgroundImage = 'linear-gradient('+deg+'deg, transparent 50%, #0E1826 50%),linear-gradient(90deg, #0E1826 50%, transparent 50%)';
  }
  else if (timePassed >= (startTime / 2)) {
    deg = -90 + (360 * timePassed / startTime);
    totalProgress.style.backgroundImage = 'linear-gradient('+deg+'deg, transparent 50%, '+progressColor+' 50%),linear-gradient(90deg, #0E1826 50%, transparent 50%)';
  }
}

function handleSecondsProgress(currentTime) {
  var progressBarColor = '';
  if (timerType === 'session') {
    progressBarColor = '#BFD7EA';
    secondsProgress.style.backgroundColor = '#BFD7EA';
  }
  else {
    progressBarColor = '#F9EDF9';
    secondsProgress.style.backgroundColor = '#F9EDF9';
  }
  var secondsPassed = 60 - convertFromSec(currentTime).seconds;
  var deg;
  if (secondsPassed < (60 / 2)) {
    deg = 90 + (360 * secondsPassed / 60)
    secondsProgress.style.backgroundImage = 'linear-gradient('+deg+'deg, transparent 50%, #0E1826 50%),linear-gradient(90deg, #0E1826 50%, transparent 50%)';
  }
  else if (secondsPassed >= (60 / 2)) {
    deg = -90 + (360 * secondsPassed / 60);
    secondsProgress.style.backgroundImage = 'linear-gradient('+deg+'deg, transparent 50%, '+progressBarColor+' 50%),linear-gradient(90deg, #0E1826 50%, transparent 50%)';
  }
}

function displayCurrentTime() {
  if (convertFromSec(currentTime).hours) {
    hoursSpan.classList.remove('hidden');
    hoursSpan.innerHTML = convertFromSec(currentTime).hours + ': ';
  } 
  else {
    hoursSpan.innerHTML = '';
  }
  minSpan.innerHTML = convertFromSec(currentTime).minutes + ': ';
  secSpan.innerHTML = convertFromSec(currentTime).seconds;
}

function addLeadingZero(time) {
  return time < 10? '0' + time : time;
}

function displayMinutes(timeInSec) {
  return parseInt(timeInSec / 60);
}

function convertFromSec(timeInSec) {
  var result = { hours: 0, minutes: 0, seconds: 0 };
  var seconds = timeInSec % 60;
  var minutes = parseInt(timeInSec / 60) % 60;
  var hours = parseInt(timeInSec / 3600);
  if (hours > 0) {
    result.hours = hours;
  }
  result.minutes = addLeadingZero(minutes);
  result.seconds = addLeadingZero(seconds);
  return result;
}

function countDown() {
  timerTypeName.innerHTML = timerType;
  if (currentTime > 0) {
    currentTime --;
    displayCurrentTime();
    handleTotalProgress(startTime, currentTime);
    handleSecondsProgress(currentTime);
    if (currentTime === 0) {
      if (timerType === 'session') {
        currentTime = breakTime;
        startTime = breakTime;
        timerType = 'break';
        timerTypeName.innerHTML = timerType;
      }
      else {
        currentTime = sessionTime;
        startTime = sessionTime;
        timerType = 'session';
        timerTypeName.innerHTML = timerType;
      }
    }
  }
}

function toggleTimer() {
  if (timerActive) {
    clearInterval(timer);
    startBtn.innerHTML = 'start';
    timerActive = false;
  }
  else {
    startBtn.innerHTML = 'pause';
    timer = setInterval(countDown, 1000);
    timerActive = true;
  }
}

function stopTimer() {
  timerActive = false;
  startBtn.innerHTML = 'start';
  clearInterval(timer);
  timerType = 'session';
  currentTime = sessionTime;
  handleTotalProgress(startTime, currentTime);
  handleSecondsProgress(currentTime);
  displayDefaultTime();
}

function displayChangedTime(e, time) {
  if (e.target.id === 'session-plus' || e.target.id === 'session-minus') {
    sessionTimeBlock.innerHTML = displayMinutes(sessionTime) + ' min';
  }
  else if (e.target.id === 'break-plus' || e.target.id === 'break-minus') {
    breakTimeBlock.innerHTML = displayMinutes(breakTime) + ' min';
  }
}

startBtn.addEventListener('click', toggleTimer);
stopBtn.addEventListener('click', stopTimer);

for (var i = 0; i < increaseButtons.length; i++) {
  increaseButtons[i].addEventListener('click', function(e) {
    if (!timerActive) {
      if (e.target.id === 'session-plus') {
        sessionTime += 60;
        currentTime = sessionTime;
        startTime = sessionTime;
        displayChangedTime(e, sessionTime);
        displayCurrentTime();
      }
      else if (e.target.id === 'break-plus') {
        breakTime += 60;
        displayChangedTime(e, breakTime);
        displayCurrentTime();
      }
    }
  });
} 

for (var i = 0; i < decreaseButtons.length; i++) {
  decreaseButtons[i].addEventListener('click', function(e) {
    if (!timerActive) {
      if (e.target.id === 'session-minus') {
        if (sessionTime > 60) {
          sessionTime -= 60;
          currentTime = sessionTime;
          startTime = sessionTime;
          displayChangedTime(e, sessionTime);
          displayCurrentTime();
        }
      }
      else if (e.target.id === 'break-minus') {
        if (breakTime > 60) {
          breakTime -= 60;
          displayChangedTime(e, breakTime);
          displayCurrentTime();
        }
      }
    }
  });
} 

document.addEventListener('DOMContentLoaded', displayDefaultTime);

By default, the session time is set to 25 minutes, and the break time is set to 5 minutes. You can adjust these durations by clicking the “+” and “-” buttons next to the session and break labels.

That’s all! hopefully, you have successfully created a Pomodoro Timerin JavaScript. If you have any questions or suggestions, feel free to comment below.

Leave a Comment

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

About CodeHim

Free Web Design Code & Scripts - CodeHim is one of the BEST developer websites that provide web designers and developers with a simple way to preview and download a variety of free code & scripts. All codes published on CodeHim are open source, distributed under OSD-compliant license which grants all the rights to use, study, change and share the software in modified and unmodified form. Before publishing, we test and review each code snippet to avoid errors, but we cannot warrant the full correctness of all content. All trademarks, trade names, logos, and icons are the property of their respective owners... find out more...

Please Rel0ad/PressF5 this page if you can't click the download/preview link

X