Apa Itu Countdown Timer?
Countdown timer merupakan alat atau fitur yang berfungsi untuk menhitung waktu mundur dari durasi yang telah di tentutkan sampai waktu selesai atau 0. Berbeda dengan stopwacth yang menghitung waktu maju
Fungsi Countdown Timer
Countdown timer dapat digunakan untuk kegiatan kehidupan sehari-hari seperti:
- Mengatur Waktu Aktivitas memasak, olah raga, belajar atau ujian yang seperti pengalaman yang saya sampaikan
- Presentasi dan Kelas dimana untuk mempermudah dalam menghitung durasi maka pada layar presentasi ditampilkan coundtown timer
- Manajemen Tugas yang membantu kita lebih tepat waktu dalam mengerjakan tugas
- Event Countdown timer untuk menghitung waktu mundur pada sebuah event
Berikut adalah jenis countdwn timer dilihat dari paltform yang digunakan
- Website jenis ini Bisa dipakai langsung tanpa instalasi dengan menampilkannya dibrowser, ada mode full screen seperti pada Contoh Countdown Timer Web Online
- Aplikasi Mobile ditampilkan pada widget di layar utama pada mobile
- Ekstensi Browser biasanya akan ditampilkan pada toolbar chrome
- Desktop App bisa digunakan secara offline di sistem operasi namun biasanya perlu instalasi jika berdasarkan
Cara membuat countdown timer online
Untuk membuat countdown timer anda bisa menggunakan skrip kode di bawah ini yang disimpan dalam ektensi .html selanjutnya anda bisa membukanya dibrowser
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Countdown Timer - Setting Waktu</title>
<style>
/* Reset & Base */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #0c0e1a 0%, #1a1f33 50%, #0f1424 100%);
padding: 1.5rem;
position: relative;
overflow-x: hidden;
}
/* Efek background bintang */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
radial-gradient(2px 2px at 20px 30px, #eee, transparent),
radial-gradient(2px 2px at 40px 70px, rgba(255,255,255,0.8), transparent),
radial-gradient(2px 2px at 50px 160px, #ddd, transparent),
radial-gradient(2px 2px at 90px 40px, rgba(255,255,255,0.6), transparent),
radial-gradient(2px 2px at 130px 80px, #fff, transparent),
radial-gradient(1px 1px at 160px 120px, #eee, transparent),
radial-gradient(2px 2px at 200px 50px, rgba(255,255,255,0.7), transparent);
background-size: 200px 200px;
background-repeat: repeat;
opacity: 0.3;
pointer-events: none;
z-index: 0;
}
/* Kartu utama */
.card {
position: relative;
z-index: 1;
max-width: 720px;
width: 100%;
background: rgba(18, 24, 45, 0.85);
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
border-radius: 60px;
padding: 2.5rem 2.5rem 2.8rem;
border: 1px solid rgba(255, 255, 255, 0.08);
box-shadow:
0 30px 60px -15px rgba(0, 0, 0, 0.8),
inset 0 1px 0 rgba(255, 255, 255, 0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-3px);
box-shadow: 0 40px 70px -15px rgba(0, 0, 0, 0.9);
}
/* Header */
.header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1.8rem;
padding-bottom: 1.2rem;
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
}
.header-left {
display: flex;
align-items: center;
gap: 0.8rem;
}
.header-left i {
font-size: 1.8rem;
color: #6c8cff;
background: rgba(108, 140, 255, 0.12);
padding: 0.6rem;
border-radius: 16px;
border: 1px solid rgba(108, 140, 255, 0.15);
}
.header-left h1 {
font-size: 1.5rem;
font-weight: 700;
color: #e8eeff;
letter-spacing: -0.02em;
}
.header-left h1 span {
color: #6c8cff;
}
.badge {
background: rgba(108, 140, 255, 0.15);
padding: 0.3rem 1rem;
border-radius: 40px;
font-size: 0.7rem;
color: #a8bfff;
border: 1px solid rgba(108, 140, 255, 0.2);
font-weight: 500;
letter-spacing: 0.3px;
text-transform: uppercase;
}
/* Timer Display */
.timer-display {
text-align: center;
padding: 1rem 0 1rem;
margin-bottom: 1.5rem;
}
.timer-numbers {
font-family: 'JetBrains Mono', 'Fira Code', monospace;
font-size: 5.2rem;
font-weight: 700;
letter-spacing: 0.08em;
background: linear-gradient(135deg, #f0f4ff 0%, #8aa8ff 100%);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: 0 0 40px rgba(108, 140, 255, 0.15);
line-height: 1.2;
transition: all 0.2s;
}
.timer-label {
font-size: 0.85rem;
color: #7a8db5;
letter-spacing: 0.15em;
text-transform: uppercase;
margin-top: 0.3rem;
font-weight: 400;
}
.timer-progress {
width: 100%;
height: 4px;
background: rgba(255, 255, 255, 0.06);
border-radius: 10px;
margin-top: 1.8rem;
overflow: hidden;
position: relative;
}
.timer-progress-bar {
height: 100%;
width: 100%;
background: linear-gradient(90deg, #6c8cff, #a78aff);
border-radius: 10px;
transition: width 0.3s linear;
box-shadow: 0 0 20px rgba(108, 140, 255, 0.3);
}
/* Setting Waktu - Jam, Menit, Detik */
.time-settings {
display: flex;
gap: 1rem;
justify-content: center;
align-items: center;
margin: 1.5rem 0 1.8rem;
flex-wrap: wrap;
background: rgba(0, 0, 0, 0.2);
padding: 1.2rem 1.5rem;
border-radius: 40px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.time-input-group {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.3rem;
}
.time-input-group label {
font-size: 0.65rem;
text-transform: uppercase;
letter-spacing: 0.1em;
color: #7a8db5;
font-weight: 600;
}
.time-input-group input {
width: 70px;
padding: 0.5rem 0.3rem;
text-align: center;
font-size: 1.3rem;
font-weight: 600;
font-family: 'JetBrains Mono', monospace;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 16px;
color: #e8eeff;
outline: none;
transition: all 0.2s;
}
.time-input-group input:focus {
border-color: #6c8cff;
background: rgba(108, 140, 255, 0.08);
box-shadow: 0 0 20px rgba(108, 140, 255, 0.1);
}
.time-input-group input::-webkit-inner-spin-button,
.time-input-group input::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
.time-input-group input[type="number"] {
-moz-appearance: textfield;
}
.time-separator {
font-size: 2rem;
font-weight: 300;
color: #4a5a7a;
padding-bottom: 0.5rem;
align-self: flex-end;
}
.btn-apply {
padding: 0.6rem 1.8rem;
border: none;
border-radius: 40px;
background: linear-gradient(135deg, #4c6ef5, #7c5cfc);
color: white;
font-weight: 600;
font-size: 0.9rem;
cursor: pointer;
transition: all 0.2s;
box-shadow: 0 4px 16px rgba(76, 110, 245, 0.25);
align-self: flex-end;
margin-bottom: 0.1rem;
}
.btn-apply:hover {
transform: translateY(-2px);
box-shadow: 0 8px 24px rgba(76, 110, 245, 0.35);
}
.btn-apply:active {
transform: scale(0.95);
}
/* Control Buttons */
.controls {
display: flex;
gap: 0.8rem;
justify-content: center;
flex-wrap: wrap;
margin: 1.8rem 0 1.5rem;
}
.btn {
display: inline-flex;
align-items: center;
gap: 0.6rem;
padding: 0.8rem 1.8rem;
border: none;
border-radius: 60px;
font-size: 0.95rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s ease;
background: rgba(255, 255, 255, 0.05);
color: #bccbff;
border: 1px solid rgba(255, 255, 255, 0.08);
backdrop-filter: blur(4px);
min-width: 110px;
justify-content: center;
}
.btn i {
font-size: 1rem;
}
.btn-primary {
background: linear-gradient(135deg, #4c6ef5, #7c5cfc);
color: white;
border: none;
box-shadow: 0 8px 24px rgba(76, 110, 245, 0.25);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 12px 32px rgba(76, 110, 245, 0.35);
}
.btn-primary:active {
transform: scale(0.95);
}
.btn-secondary {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.1);
}
.btn-secondary:hover {
background: rgba(255, 255, 255, 0.12);
transform: translateY(-2px);
}
.btn-danger {
background: rgba(239, 68, 68, 0.15);
border: 1px solid rgba(239, 68, 68, 0.25);
color: #fca5a5;
}
.btn-danger:hover {
background: rgba(239, 68, 68, 0.25);
transform: translateY(-2px);
}
.btn:disabled {
opacity: 0.4;
cursor: not-allowed;
transform: none !important;
}
/* Presets */
.presets {
display: flex;
gap: 0.6rem;
justify-content: center;
flex-wrap: wrap;
margin-top: 0.5rem;
}
.preset-btn {
padding: 0.4rem 1.2rem;
border-radius: 40px;
border: 1px solid rgba(255, 255, 255, 0.06);
background: rgba(255, 255, 255, 0.03);
color: #8b9fc9;
font-size: 0.8rem;
font-weight: 500;
cursor: pointer;
transition: all 0.2s;
font-family: inherit;
}
.preset-btn:hover {
background: rgba(108, 140, 255, 0.12);
border-color: rgba(108, 140, 255, 0.25);
color: #d6e2ff;
transform: translateY(-1px);
}
.preset-btn.active {
background: rgba(108, 140, 255, 0.15);
border-color: #4c6ef5;
color: #fff;
}
/* Status */
.status {
display: flex;
align-items: center;
justify-content: center;
gap: 0.6rem;
margin-top: 1.8rem;
padding-top: 1.2rem;
border-top: 1px solid rgba(255, 255, 255, 0.04);
color: #6a7fa8;
font-size: 0.85rem;
}
.status i {
font-size: 0.8rem;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
transition: background 0.3s;
}
.status-dot.idle {
background: #6a7fa8;
}
.status-dot.running {
background: #4ade80;
box-shadow: 0 0 12px rgba(74, 222, 128, 0.4);
animation: pulse-dot 1.2s infinite;
}
.status-dot.paused {
background: #fbbf24;
box-shadow: 0 0 12px rgba(251, 191, 36, 0.3);
}
.status-dot.finished {
background: #f87171;
box-shadow: 0 0 12px rgba(248, 113, 113, 0.3);
}
@keyframes pulse-dot {
0%, 100% { opacity: 1; transform: scale(1); }
50% { opacity: 0.6; transform: scale(0.85); }
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.08); color: #ff8a8a; }
100% { transform: scale(1); }
}
/* Responsive */
@media (max-width: 650px) {
.card {
padding: 1.8rem 1.5rem 2rem;
border-radius: 40px;
}
.timer-numbers {
font-size: 3.8rem;
}
.time-settings {
padding: 1rem;
gap: 0.5rem;
}
.time-input-group input {
width: 55px;
font-size: 1.1rem;
padding: 0.4rem 0.2rem;
}
.time-separator {
font-size: 1.5rem;
}
.btn-apply {
padding: 0.5rem 1.2rem;
font-size: 0.8rem;
}
.header-left h1 {
font-size: 1.2rem;
}
.header-left i {
font-size: 1.4rem;
padding: 0.5rem;
}
.btn {
padding: 0.7rem 1.2rem;
font-size: 0.85rem;
min-width: 90px;
}
}
@media (max-width: 450px) {
.timer-numbers {
font-size: 2.8rem;
}
.time-settings {
flex-wrap: wrap;
justify-content: center;
}
.time-input-group input {
width: 50px;
font-size: 1rem;
}
.time-separator {
display: none;
}
.controls {
gap: 0.5rem;
}
.btn {
padding: 0.6rem 1rem;
font-size: 0.8rem;
min-width: 70px;
}
.preset-btn {
font-size: 0.7rem;
padding: 0.3rem 0.8rem;
}
}
</style>
</head>
<body>
<div class="card">
<!-- Header -->
<div class="header">
<div class="header-left">
<i class="fas fa-clock"></i>
<h1>Count<span>down</span></h1>
</div>
<span class="badge">⏱️ setting waktu</span>
</div>
<!-- Timer Display -->
<div class="timer-display">
<div class="timer-numbers" id="timerDisplay">00:05:00</div>
<div class="timer-label">Waktu tersisa</div>
<div class="timer-progress">
<div class="timer-progress-bar" id="progressBar" style="width: 100%"></div>
</div>
</div>
<!-- Setting Waktu: Jam, Menit, Detik -->
<div class="time-settings">
<div class="time-input-group">
<label for="inputJam">Jam</label>
<input type="number" id="inputJam" min="0" max="99" value="0">
</div>
<span class="time-separator">:</span>
<div class="time-input-group">
<label for="inputMenit">Menit</label>
<input type="number" id="inputMenit" min="0" max="59" value="5">
</div>
<span class="time-separator">:</span>
<div class="time-input-group">
<label for="inputDetik">Detik</label>
<input type="number" id="inputDetik" min="0" max="59" value="0">
</div>
<button class="btn-apply" id="applyTimeBtn">
<i class="fas fa-check"></i> Terapkan
</button>
</div>
<!-- Controls -->
<div class="controls">
<button class="btn btn-primary" id="startBtn">
<i class="fas fa-play"></i> Mulai
</button>
<button class="btn btn-secondary" id="pauseBtn" disabled>
<i class="fas fa-pause"></i> Jeda
</button>
<button class="btn btn-secondary" id="resumeBtn" disabled>
<i class="fas fa-play"></i> Lanjut
</button>
<button class="btn btn-danger" id="resetBtn">
<i class="fas fa-undo"></i> Reset
</button>
</div>
<!-- Presets -->
<div class="presets">
<button class="preset-btn" data-hours="0" data-minutes="1" data-seconds="0">1 menit</button>
<button class="preset-btn active" data-hours="0" data-minutes="5" data-seconds="0">5 menit</button>
<button class="preset-btn" data-hours="0" data-minutes="10" data-seconds="0">10 menit</button>
<button class="preset-btn" data-hours="0" data-minutes="30" data-seconds="0">30 menit</button>
<button class="preset-btn" data-hours="1" data-minutes="0" data-seconds="0">1 jam</button>
<button class="preset-btn" data-hours="2" data-minutes="0" data-seconds="0">2 jam</button>
</div>
<!-- Status -->
<div class="status">
<span class="status-dot idle" id="statusDot"></span>
<span id="statusText">Siap</span>
<span style="margin-left: 0.5rem; opacity: 0.4;">|</span>
<span id="timeElapsed" style="opacity: 0.6;">00:00:00</span>
</div>
</div>
<!-- Font Awesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<script>
(function() {
'use strict';
// DOM Elements
const timerDisplay = document.getElementById('timerDisplay');
const progressBar = document.getElementById('progressBar');
const startBtn = document.getElementById('startBtn');
const pauseBtn = document.getElementById('pauseBtn');
const resumeBtn = document.getElementById('resumeBtn');
const resetBtn = document.getElementById('resetBtn');
const statusDot = document.getElementById('statusDot');
const statusText = document.getElementById('statusText');
const timeElapsed = document.getElementById('timeElapsed');
const presetBtns = document.querySelectorAll('.preset-btn');
const inputJam = document.getElementById('inputJam');
const inputMenit = document.getElementById('inputMenit');
const inputDetik = document.getElementById('inputDetik');
const applyTimeBtn = document.getElementById('applyTimeBtn');
// State
let totalSeconds = 300; // 5 menit default
let remainingSeconds = totalSeconds;
let elapsedSeconds = 0;
let timerInterval = null;
let isRunning = false;
let isPaused = false;
let isFinished = false;
// Format waktu HH:MM:SS
function formatTime(seconds) {
const hrs = Math.floor(seconds / 3600);
const mins = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
return `${String(hrs).padStart(2, '0')}:${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
}
// Update tampilan timer & progress
function updateDisplay() {
timerDisplay.textContent = formatTime(remainingSeconds);
const progress = totalSeconds > 0 ? (remainingSeconds / totalSeconds) * 100 : 0;
progressBar.style.width = `${Math.max(0, progress)}%`;
// Update elapsed time
const elapsed = totalSeconds - remainingSeconds;
timeElapsed.textContent = formatTime(Math.max(0, elapsed));
}
// Update status dot & text
function updateStatus(state, msg) {
statusDot.className = 'status-dot';
if (state === 'idle') {
statusDot.classList.add('idle');
statusText.textContent = msg || 'Siap';
} else if (state === 'running') {
statusDot.classList.add('running');
statusText.textContent = msg || 'Berjalan...';
} else if (state === 'paused') {
statusDot.classList.add('paused');
statusText.textContent = msg || 'Dijeda';
} else if (state === 'finished') {
statusDot.classList.add('finished');
statusText.textContent = msg || 'Selesai!';
}
}
// Hentikan interval
function stopTimer() {
if (timerInterval) {
clearInterval(timerInterval);
timerInterval = null;
}
isRunning = false;
isPaused = false;
}
// Mulai timer (internal)
function startTimerInternal() {
if (timerInterval) return;
if (remainingSeconds <= 0) {
resetTimer();
return;
}
isRunning = true;
isPaused = false;
isFinished = false;
updateStatus('running', 'Berjalan...');
// Update button states
startBtn.disabled = true;
pauseBtn.disabled = false;
resumeBtn.disabled = true;
resetBtn.disabled = false;
timerInterval = setInterval(() => {
if (remainingSeconds > 0) {
remainingSeconds--;
elapsedSeconds++;
updateDisplay();
// Cek jika waktu habis
if (remainingSeconds === 0) {
stopTimer();
isFinished = true;
updateStatus('finished', '⏰ Waktu habis!');
startBtn.disabled = false;
pauseBtn.disabled = true;
resumeBtn.disabled = true;
// Trigger animasi
timerDisplay.style.animation = 'none';
setTimeout(() => {
timerDisplay.style.animation = 'pulse 0.6s ease 3';
}, 10);
// Play sound effect via Web Audio
try {
const ctx = new (window.AudioContext || window.webkitAudioContext)();
const osc = ctx.createOscillator();
const gain = ctx.createGain();
osc.connect(gain);
gain.connect(ctx.destination);
osc.frequency.value = 880;
gain.gain.value = 0.15;
osc.start();
osc.stop(ctx.currentTime + 0.3);
} catch(e) { /* silent fallback */ }
}
}
}, 1000);
}
// Jeda timer
function pauseTimer() {
if (!isRunning || isPaused) return;
stopTimer();
isPaused = true;
updateStatus('paused', 'Dijeda');
startBtn.disabled = true;
pauseBtn.disabled = true;
resumeBtn.disabled = false;
resetBtn.disabled = false;
}
// Lanjutkan timer
function resumeTimer() {
if (!isPaused || isFinished) return;
if (remainingSeconds <= 0) {
resetTimer();
return;
}
startTimerInternal();
pauseBtn.disabled = false;
resumeBtn.disabled = true;
startBtn.disabled = true;
}
// Reset timer
function resetTimer() {
stopTimer();
isRunning = false;
isPaused = false;
isFinished = false;
remainingSeconds = totalSeconds;
elapsedSeconds = 0;
updateDisplay();
updateStatus('idle', 'Siap');
startBtn.disabled = false;
pauseBtn.disabled = true;
resumeBtn.disabled = true;
resetBtn.disabled = false;
progressBar.style.width = '100%';
// Update input fields sesuai totalSeconds
const hrs = Math.floor(totalSeconds / 3600);
const mins = Math.floor((totalSeconds % 3600) / 60);
const secs = totalSeconds % 60;
inputJam.value = hrs;
inputMenit.value = mins;
inputDetik.value = secs;
}
// Set waktu baru dari jam, menit, detik
function setTimeFromInputs() {
if (isRunning) {
stopTimer();
}
let jam = parseInt(inputJam.value) || 0;
let menit = parseInt(inputMenit.value) || 0;
let detik = parseInt(inputDetik.value) || 0;
// Validasi
jam = Math.max(0, jam);
menit = Math.max(0, Math.min(59, menit));
detik = Math.max(0, Math.min(59, detik));
totalSeconds = (jam * 3600) + (menit * 60) + detik;
if (totalSeconds === 0) {
totalSeconds = 1; // Minimal 1 detik
inputDetik.value = 1;
}
remainingSeconds = totalSeconds;
elapsedSeconds = 0;
isRunning = false;
isPaused = false;
isFinished = false;
updateDisplay();
updateStatus('idle', 'Siap');
startBtn.disabled = false;
pauseBtn.disabled = true;
resumeBtn.disabled = true;
resetBtn.disabled = false;
// Update preset aktif
presetBtns.forEach(btn => {
const h = parseInt(btn.dataset.hours) || 0;
const m = parseInt(btn.dataset.minutes) || 0;
const s = parseInt(btn.dataset.seconds) || 0;
const presetTotal = (h * 3600) + (m * 60) + s;
btn.classList.toggle('active', presetTotal === totalSeconds);
});
}
// Set waktu dari preset
function setTimeFromPreset(hours, minutes, seconds) {
const jam = parseInt(hours) || 0;
const menit = parseInt(minutes) || 0;
const detik = parseInt(seconds) || 0;
inputJam.value = jam;
inputMenit.value = menit;
inputDetik.value = detik;
setTimeFromInputs();
}
// --- Event Listeners ---
startBtn.addEventListener('click', startTimerInternal);
pauseBtn.addEventListener('click', pauseTimer);
resumeBtn.addEventListener('click', resumeTimer);
resetBtn.addEventListener('click', resetTimer);
applyTimeBtn.addEventListener('click', setTimeFromInputs);
// Preset buttons
presetBtns.forEach(btn => {
btn.addEventListener('click', function(e) {
const hours = this.dataset.hours || 0;
const minutes = this.dataset.minutes || 0;
const seconds = this.dataset.seconds || 0;
setTimeFromPreset(hours, minutes, seconds);
});
});
// Keyboard shortcuts (spasi untuk start/pause)
document.addEventListener('keydown', function(e) {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
if (e.code === 'Space') {
e.preventDefault();
if (isRunning && !isPaused) {
pauseTimer();
} else if (isPaused && !isFinished) {
resumeTimer();
} else if (!isRunning && !isPaused && !isFinished) {
startTimerInternal();
}
}
if (e.code === 'KeyR') {
resetTimer();
}
});
// Enter pada input untuk apply
[inputJam, inputMenit, inputDetik].forEach(input => {
input.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
setTimeFromInputs();
}
});
});
// Inisialisasi
resetTimer();
console.log('⏱️ Countdown Timer siap! Shortcut: Spasi (start/pause), R (reset)');
console.log('💡 Atur waktu di kolom Jam, Menit, Detik lalu klik "Terapkan"');
})();
</script>
</body>
</html>

Post a Comment