JavaScript Countdown Timer With Start Stop Buttons


Create a functional JavaScript Countdown Timer with Start and Stop buttons. This tool is perfect for showing time left for an event, a deadline, or a quiz timer. Below you can test the live demo and get the complete HTML, CSS, and JavaScript code snippet to use directly in your projects.

Demo: Countdown Timer

How to Use the Timer

Using the timer is simple. Enter a custom duration in seconds, click "Start" to begin, or "Pause" to take a break. The "Reset" button restores the initial time. A blinking display and sound effect signal when the time is up.

00:00:30

Features

  • ⏱️ Displays time in HH:MM:SS format
  • πŸ–ŠοΈ Accepts custom time input (in seconds)
  • ▢️ Start, ⏸️ Pause, and πŸ” Resume controls
  • πŸ”„ Reset button to restart the timer
  • πŸ”” Plays sound and visual blink on completion
  • πŸ“ Updates browser tab title with time left

JavaScript Countdown Timer Code

Complete code HTML, CSS and JavaScript

HTML
<div id="timer">00:30</div>
<input id="time-input" type="number" min="1" placeholder="Seconds" value="30">
<button id="start-button">Start</button>
<button id="reset-button">Reset</button>
CSS
body {
    font-family: Arial, sans-serif;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100vh;
    margin: 0;
}

#timer {
    font-size: 48px;
    margin: 20px 0;
    color: #007bff;
}

input#time-input {
    padding: 8px;
    margin: 10px;
    font-size: 1em;
    width: 100px;
}

button {
    padding: 10px 20px;
    font-size: 18px;
    margin: 10px;
    border: none;
    border-radius: 5px;
    cursor: pointer;
}

button#start-button {
    background-color: #28a745;
    color: white;
}

button#reset-button {
    background-color: #dc3545;
    color: white;
}

.blink {
    animation: blink 1s step-end infinite;
}

@keyframes blink {
    50% {
        opacity: 0;
    }
}
JavaScript
const DEFAULT_TIME = 30;
const TIMER_INTERVAL_MS = 1000;
const BLINK_CLASS = 'blink';
const BEEP_SOUND_URL = 'https://www.soundjay.com/buttons/beep-01a.mp3';

let countdownInterval;
let initialTime = DEFAULT_TIME;
let timeLeft = initialTime;
let isRunning = false;


const timerDisplay = document.getElementById("timer");
const startPauseBtn = document.getElementById("start-button");
const resetBtn = document.getElementById("reset-button");
const timeInput = document.getElementById("time-input");

const formatTime = seconds => {
    const hrs = Math.floor(seconds / 3600);
    const mins = Math.floor((seconds % 3600) / 60);
    const secs = seconds % 60;
    return [hrs, mins, secs].map(unit => String(unit).padStart(2, '0')).join(':');
};

const updateDisplay = seconds => {
    const formatted = formatTime(seconds);
    timerDisplay.textContent = formatted;
    document.title = `Timer: ${formatted}`;
};

const playEndSound = () => {
    const beep = new Audio(BEEP_SOUND_URL);
    beep.play().catch(console.error);
};

const onTimeEnd = () => {
    isRunning = false;
    startPauseBtn.textContent = 'Start';
    startPauseBtn.disabled = false;
    playEndSound();
    timerDisplay.classList.add(BLINK_CLASS);

    // callback_time_end(); // hook for callback
};

const startCountdown = () => {
    isRunning = true;
    startPauseBtn.textContent = 'Pause';
    startPauseBtn.disabled = false;
    countdownInterval = setInterval(() => {
        if (timeLeft > 0) {
            timeLeft--;
            updateDisplay(timeLeft);
        } else {
            clearInterval(countdownInterval);
            onTimeEnd();
        }
    }, TIMER_INTERVAL_MS);
};

const pauseCountdown = () => {
    clearInterval(countdownInterval);
    isRunning = false;
    startPauseBtn.textContent = 'Resume';
};

const handleStartPause = () => {
    if (isRunning) {
        pauseCountdown();
    } else {
        if (timeInput?.value) {
            const newTime = parseInt(timeInput.value, 10);
            if (isNaN(newTime) || newTime <= 0) {
                alert("Please enter a valid time in seconds.");
                return;
            }
            initialTime = newTime;
            if (timeLeft === 0 || timeLeft === DEFAULT_TIME) {
                timeLeft = initialTime;
                updateDisplay(timeLeft);
            }
        }
        startCountdown();
    }
};

const resetCountdown = () => {
    clearInterval(countdownInterval);
    isRunning = false;
    timeLeft = initialTime;
    updateDisplay(timeLeft);
    startPauseBtn.textContent = 'Start';
    startPauseBtn.disabled = false;
    timerDisplay.classList.remove(BLINK_CLASS);
};

const handleTimeInputChange = () => {
    if (isRunning) return;
    const newTime = parseInt(timeInput.value, 10);
    if (!isNaN(newTime) && newTime > 0) {
        initialTime = newTime;
        timeLeft = initialTime;
        updateDisplay(timeLeft);
    }
};

updateDisplay(timeLeft);

startPauseBtn.addEventListener("click", handleStartPause);
resetBtn.addEventListener("click", resetCountdown);
timeInput.addEventListener("change", handleTimeInputChange);