Как создать онлайн-таймер для сайта своими руками
Чтобы сделать работающий онлайн-таймер в браузере, нужно объединить 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. Это обновляет заголовок вкладки браузера. Пользователь увидит обратный отсчет, даже если переключится на другую вкладку, что очень удобно для многозадачности.
Частые ошибки при реализации
-
Накопление погрешности
setInterval. Браузеры не гарантируют точностьsetInterval. Для простых кухонных таймеров это не критично, но для спортивных секундомеров лучше использоватьDate.now()для вычисления разницы во времени, а не просто уменьшать переменную на 1. -
Блокировка автовоспроизведения звука. Современные браузеры (Chrome, Safari) запрещают воспроизводить звук без действия пользователя. Поэтому звуковой сигнал сработает только если пользователь предварительно взаимодействовал со страницей (нажал "Старт").
-
Отсутствие блокировки ввода. Если пользователь меняет цифры в полях ввода во время работы таймера, это может сломать логику. В коде выше поля ввода блокируются (
disabled) при старте.
FAQ
Как изменить звук окончания таймера?
Замените ссылку в атрибуте src тега <audio> на путь к вашему файлу (например, sounds/my-beep.mp3). Убедитесь, что файл доступен на сервере.
Можно ли сделать таймер круглым (как в iOS)?
Да, для этого нужно добавить SVG-круг или использовать CSS conic-gradient в качестве фона для .timer-display, динамически меняя его заполнение в функции updateDisplay.
Почему таймер останавливается, когда я сворачиваю браузер?
В некоторых мобильных браузерах фоновые процессы замораживаются для экономии энергии. Использование Web Workers или синхронизация с системным временем (Date.now()) при возвращении на вкладку помогает решить эту проблему.