Как создать онлайн-таймер для сайта своими руками

Иван Корнев·28.04.2026·2 мин

Чтобы сделать работающий онлайн-таймер в браузере, нужно объединить HTML-разметку для отображения цифр, CSS для стилей и JavaScript для логики обратного отсчета. Ниже представлен готовый, адаптивный код таймера с функциями запуска, паузы, сброса и звуковым уведомлением, который можно сразу вставить на любую веб-страницу.

Этот инструмент полезен для лендингов, страниц с рецептами, образовательных платформ или личных проектов, где важно контролировать время выполнения задачи прямо в интерфейсе сайта.

Зачем писать свой таймер? Готовые виджеты часто перегружены рекламой или имеют чужой дизайн. Собственный код весит всего пару килобайт, полностью настраивается под стиль вашего сайта и не зависит от сторонних сервисов.

Базовая структура: HTML

Разметка должна быть семантически верной и доступной. Мы используем поля ввода для настройки времени и кнопки управления. Атрибуты aria помогут пользователям скринридеров понимать состояние таймера.

<div class="timer-container">
  <div class="timer-display" id="display">00:00:00</div>
  
  <div class="timer-inputs">
    <input type="number" id="hours" placeholder="Ч" min="0" max="99" value="0">
    <span>:</span>
    <input type="number" id="minutes" placeholder="М" min="0" max="59" value="5">
    <span>:</span>
    <input type="number" id="seconds" placeholder="С" min="0" max="59" value="0">
  </div>

  <div class="timer-controls">
    <button id="startBtn">Старт</button>
    <button id="pauseBtn" disabled>Пауза</button>
    <button id="resetBtn">Сброс</button>
  </div>
  
  <!-- Скрытый аудио элемент для сигнала -->
  <audio id="alarmSound" src="https://actions.google.com/sounds/v1/alarms/beep_short.ogg"></audio>
</div>

Стилизация: CSS

Добавим современный лаконичный дизайн. Таймер будет центрирован, цифры — крупными и читаемыми, а кнопки — удобными для нажатия на мобильных устройствах.

.timer-container {
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  max-width: 400px;
  margin: 20px auto;
  padding: 20px;
  border-radius: 12px;
  background: #f8f9fa;
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
  text-align: center;
}

.timer-display {
  font-size: 3rem;
  font-weight: 700;
  color: #333;
  margin-bottom: 15px;
  font-variant-numeric: tabular-nums; /* Чтобы цифры не прыгали */
}

.timer-inputs {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 5px;
  margin-bottom: 20px;
}

.timer-inputs input {
  width: 50px;
  padding: 8px;
  text-align: center;
  border: 1px solid #ddd;
  border-radius: 6px;
  font-size: 1rem;
}

.timer-controls button {
  padding: 10px 20px;
  margin: 0 5px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-weight: 600;
  transition: background 0.2s;
}

#startBtn { background: #28a745; color: white; }
#startBtn:hover { background: #218838; }
#startBtn:disabled { background: #94d3a2; cursor: not-allowed; }

#pauseBtn { background: #ffc107; color: #333; }
#pauseBtn:hover { background: #e0a800; }
#pauseBtn:disabled { background: #ffeeba; cursor: not-allowed; }

#resetBtn { background: #dc3545; color: white; }
#resetBtn:hover { background: #c82333; }

Логика работы: JavaScript

Скрипт обрабатывает ввод пользователя, запускает интервал обновления каждую секунду и корректно останавливает отсчет.

document.addEventListener('DOMContentLoaded', () => {
  const display = document.getElementById('display');
  const hoursInput = document.getElementById('hours');
  const minutesInput = document.getElementById('minutes');
  const secondsInput = document.getElementById('seconds');
  const startBtn = document.getElementById('startBtn');
  const pauseBtn = document.getElementById('pauseBtn');
  const resetBtn = document.getElementById('resetBtn');
  const alarmSound = document.getElementById('alarmSound');

  let countdown;
  let totalSeconds = 0;
  let isRunning = false;

  // Форматирование времени (добавление ведущего нуля)
  function formatTime(time) {
    return time < 10 ? `0${time}` : time;
  }

  // Обновление экрана
  function updateDisplay(seconds) {
    const h = Math.floor(seconds / 3600);
    const m = Math.floor((seconds % 3600) / 60);
    const s = seconds % 60;
    display.textContent = `${formatTime(h)}:${formatTime(m)}:${formatTime(s)}`;
    document.title = `${formatTime(h)}:${formatTime(m)}:${formatTime(s)} - Таймер`; // Время в заголовке вкладки
  }

  // Запуск таймера
  function startTimer() {
    if (isRunning) return;
    
    // Если таймер был на паузе, продолжаем. Если сброшен - считываем инпуты
    if (totalSeconds === 0) {
      const h = parseInt(hoursInput.value) || 0;
      const m = parseInt(minutesInput.value) || 0;
      const s = parseInt(secondsInput.value) || 0;
      totalSeconds = h * 3600 + m * 60 + s;
    }

    if (totalSeconds <= 0) {
      alert("Пожалуйста, установите время больше 0");
      return;
    }

    isRunning = true;
    toggleButtons(true);
    
    // Сразу обновляем дисплей, чтобы не ждать 1 секунду
    updateDisplay(totalSeconds);

    countdown = setInterval(() => {
      totalSeconds--;
      updateDisplay(totalSeconds);

      if (totalSeconds <= 0) {
        clearInterval(countdown);
        timerFinished();
      }
    }, 1000);
  }

  // Пауза
  function pauseTimer() {
    clearInterval(countdown);
    isRunning = false;
    toggleButtons(false);
  }

  // Сброс
  function resetTimer() {
    clearInterval(countdown);
    isRunning = false;
    totalSeconds = 0;
    updateDisplay(0);
    toggleButtons(false);
    // Сброс значений в инпутах к дефолтным (опционально)
    hoursInput.value = 0;
    minutesInput.value = 5;
    secondsInput.value = 0;
  }

  // Завершение таймера
  function timerFinished() {
    isRunning = false;
    toggleButtons(false);
    display.style.color = "#dc3545"; // Красный цвет при окончании
    try {
      alarmSound.play();
    } catch (e) {
      console.log("Автовоспроизведение звука заблокировано браузером");
    }
    setTimeout(() => { display.style.color = "#333"; }, 3000);
  }

  // Управление состоянием кнопок
  function toggleButtons(running) {
    startBtn.disabled = running;
    pauseBtn.disabled = !running;
    hoursInput.disabled = running;
    minutesInput.disabled = running;
    secondsInput.disabled = running;
  }

  // Слушатели событий
  startBtn.addEventListener('click', startTimer);
  pauseBtn.addEventListener('click', pauseTimer);
  resetBtn.addEventListener('click', resetTimer);
});

Совет по UX: Обратите внимание на строку document.title = ... в JavaScript. Это обновляет заголовок вкладки браузера. Пользователь увидит обратный отсчет, даже если переключится на другую вкладку, что очень удобно для многозадачности.

Частые ошибки при реализации

  1. Накопление погрешности setInterval. Браузеры не гарантируют точность setInterval. Для простых кухонных таймеров это не критично, но для спортивных секундомеров лучше использовать Date.now() для вычисления разницы во времени, а не просто уменьшать переменную на 1.

  2. Блокировка автовоспроизведения звука. Современные браузеры (Chrome, Safari) запрещают воспроизводить звук без действия пользователя. Поэтому звуковой сигнал сработает только если пользователь предварительно взаимодействовал со страницей (нажал "Старт").

  3. Отсутствие блокировки ввода. Если пользователь меняет цифры в полях ввода во время работы таймера, это может сломать логику. В коде выше поля ввода блокируются (disabled) при старте.

FAQ

Как изменить звук окончания таймера? Замените ссылку в атрибуте src тега <audio> на путь к вашему файлу (например, sounds/my-beep.mp3). Убедитесь, что файл доступен на сервере.

Можно ли сделать таймер круглым (как в iOS)? Да, для этого нужно добавить SVG-круг или использовать CSS conic-gradient в качестве фона для .timer-display, динамически меняя его заполнение в функции updateDisplay.

Почему таймер останавливается, когда я сворачиваю браузер? В некоторых мобильных браузерах фоновые процессы замораживаются для экономии энергии. Использование Web Workers или синхронизация с системным временем (Date.now()) при возвращении на вкладку помогает решить эту проблему.