JavaScript

Hướng dẫn tạo đồng hồ đếm ngược bằng HTML, CSS, JS

Admin
Jul 12, 2025
3 phút đọc
668

Đồng hồ đếm ngược là một tiện ích cực kỳ hữu ích trong nhiều tình huống như sự kiện, học tập, thể thao, hoặc đơn giản là làm công cụ nhắc nhở. Trong bài viết này, CodeTutHub sẽ hướng dẫn bạn cách tạo một Countdown Timer tùy chỉnh bằng HTML, CSS và JavaScript thuần, có đầy đủ chức năng:

  • Nhập giờ / phút / giây
  • Bắt đầu đếm ngược
  • Tạm dừng / tiếp tục
  • Đặt lại (reset)

🧱 Giao Diện Cơ Bản

Chúng ta sẽ có một giao diện thân thiện với:

  • 3 input nhập giờ, phút, giây
  • Các nút điều khiển: Start, Pause/Resume, Reset
  • Đồng hồ hiển thị đếm ngược thời gian còn lại
  • Khi hết thời gian, hiển thị thông báo "⏰ Time off" màu đỏ

📦 Mã nguồn đầy đủ

Dưới đây là mã HTML + CSS + JavaScript bạn có thể dùng ngay:

html
<!DOCTYPE html>
<html lang="vi">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  <title>Countdown Hoàn Chỉnh - CodeTutHub</title>
  <style>
    body {
      background: #f9fafb;
      font-family: 'Segoe UI', sans-serif;
      display: flex;
      flex-direction: column;
      align-items: center;
      padding-top: 50px;
    }
    .input-group {
      display: flex;
      gap: 10px;
      margin-bottom: 20px;
      flex-wrap: wrap;
      justify-content: center;
    }
    input {
      width: 70px;
      padding: 8px;
      text-align: center;
      border: 1px solid #d1d5db;
      border-radius: 8px;
    }
    button {
      padding: 8px 16px;
      background-color: #2563eb;
      color: white;
      border: none;
      border-radius: 8px;
      cursor: pointer;
    }
    .countdown {
      display: flex;
      gap: 20px;
      margin-top: 20px;
      font-size: 2rem;
    }
    .message {
      margin-top: 30px;
      font-size: 1.5rem;
      font-weight: bold;
      color: red;
    }
  </style>
</head>
<body>
  <h2>Nhập thời gian đếm ngược</h2>
  <div class="input-group">
    <input type="number" id="hours" placeholder="Giờ" min="0" />
    <input type="number" id="minutes" placeholder="Phút" min="0" />
    <input type="number" id="seconds" placeholder="Giây" min="0" />
    <button onclick="startCountdown()" id="startBtn">Start</button>
    <button onclick="togglePause()" id="pauseBtn" style="display:none;">Pause</button>
    <button onclick="resetCountdown()" id="resetBtn" style="display:none;">Reset</button>
  </div>

  <div class="countdown" id="countdownDisplay" style="display: none;">
    <span id="h">00</span>:
    <span id="m">00</span>:
    <span id="s">00</span>
  </div>
  <div class="message" id="message"></div>

  <script>
    let interval;
    let totalSeconds = 0;
    let isPaused = false;

    function startCountdown() {
      clearInterval(interval);
      document.getElementById("message").textContent = "";

      const hour = parseInt(document.getElementById("hours").value) || 0;
      const minute = parseInt(document.getElementById("minutes").value) || 0;
      const second = parseInt(document.getElementById("seconds").value) || 0;

      totalSeconds = hour * 3600 + minute * 60 + second;

      if (totalSeconds <= 0) {
        alert("Vui lòng nhập thời gian lớn hơn 0!");
        return;
      }

      disableInputs(true);
      toggleButtons({ pause: true, reset: true });

      document.getElementById("countdownDisplay").style.display = "flex";
      updateDisplay();
      interval = setInterval(tick, 1000);
    }

    function tick() {
      if (!isPaused && totalSeconds > 0) {
        totalSeconds--;
        updateDisplay();
      }

      if (totalSeconds <= 0) {
        clearInterval(interval);
        document.getElementById("message").textContent = "⏰ Time off";
        toggleButtons({ pause: false, reset: true });
      }
    }

    function updateDisplay() {
      const h = Math.floor(totalSeconds / 3600);
      const m = Math.floor((totalSeconds % 3600) / 60);
      const s = totalSeconds % 60;

      document.getElementById("h").textContent = String(h).padStart(2, '0');
      document.getElementById("m").textContent = String(m).padStart(2, '0');
      document.getElementById("s").textContent = String(s).padStart(2, '0');
    }

    function togglePause() {
      isPaused = !isPaused;
      document.getElementById("pauseBtn").textContent = isPaused ? "Resume" : "Pause";
    }

    function resetCountdown() {
      clearInterval(interval);
      totalSeconds = 0;
      isPaused = false;

      document.getElementById("h").textContent = "00";
      document.getElementById("m").textContent = "00";
      document.getElementById("s").textContent = "00";
      document.getElementById("message").textContent = "";
      document.getElementById("countdownDisplay").style.display = "none";

      disableInputs(false);
      document.getElementById("pauseBtn").textContent = "Pause";
      toggleButtons({ pause: false, reset: false });
    }

    function disableInputs(disable) {
      document.getElementById("hours").disabled = disable;
      document.getElementById("minutes").disabled = disable;
      document.getElementById("seconds").disabled = disable;
      document.getElementById("startBtn").disabled = disable;
    }

    function toggleButtons({ pause = false, reset = false }) {
      document.getElementById("pauseBtn").style.display = pause ? "inline-block" : "none";
      document.getElementById("resetBtn").style.display = reset ? "inline-block" : "none";
    }
  </script>
</body>
</html>

✅ Tính năng được hỗ trợ

Tính năngTrạng thái
Nhập thời gian (giờ, phút, giây)✅ Có
Bắt đầu đếm ngược✅ Có
Tạm dừng / Tiếp tục✅ Có
Reset (đặt lại mọi thứ)✅ Có
Hiển thị “Time off” khi hết giờ✅ Có

🧠 Gợi ý mở rộng

  • ✅ Thêm âm thanh khi hết giờ
  • ✅ Hỗ trợ chạy nhiều đồng hồ cùng lúc
  • 🌙 Bật Dark Mode bằng Tailwind
  • 📦 Xuất thành React Component hoặc Vue Component
  • 🔄 Tùy chọn lặp lại sau khi đếm hết
Toàn Nguyễn
Toàn NguyễnTác giả

Tác giả tại CodeTutHub

Xin chào, mình là Toàn 👋
Là Senior Full-Stack Developer ở HCM, đồng thời là người đứng sau CodeTutHub. Mình viết về những gì mình thực sự dùng hàng ngày — từ Laravel, Next.js, đến cách workflow lập trình với AI agents như Claude Code và Cursor.
Nếu bạn thấy bài này hữu ích, hãy subscribe newsletter hoặc kết nối với mình. Mình luôn sẵn sàng thảo luận về dự án thú vị, cơ hội remote, hoặc đơn giản là chat về tech.
Ho Chi Minh City · Open for collaboration

0 Bình luận

Chưa có bình luận nào. Hãy là người đầu tiên!
Đang trả lời
Xoá bình luận

Bạn có chắc muốn xoá bình luận này?
Hành động này không thể hoàn tác.

Thông báo hệ thống
Thông tin