Таймер обратного отсчёта на чистом JavaScript

В этой статье рассмотрим таймер обратного отсчета, построенный на чистом CSS и JavaScript. Он написан с использованием минимального количества кода без использования jQuery и каких-либо других сторонних библиотек.
Таймеры обратного отсчёта могут использоваться на сайтах для различных целей. Но в большинстве случаев они применяются для отображения времени, которое осталось до наступления какого-то крупного события: запуска нового продукта, рекламной акции, начала распродажи и т.д.
Демо таймера обратного отсчёта
Простой таймер обратного отсчета с днями, часами, минутами и секундами. Очень легко настраивается. Создан на чистом CSS и Javascript (без зависимостей).

Подключение и настройка таймера
1. Вставить в нужное место страницы html-разметку таймера:
<div class="timer">
<div class="timer__items">
<div class="timer__item timer__days">00</div>
<div class="timer__item timer__hours">00</div>
<div class="timer__item timer__minutes">00</div>
<div class="timer__item timer__seconds">00</div>
</div>
</div>
Таймер обратного отсчета отображает четыре числа: дни, часы, минуты и секунды. Каждое число находится в элементе <div>
. Первый класс (timer__item
) используется для стилизации элемента, а второй - для таргетинга в JavaScript.
2. Добавить стили (базовое оформление):
.timer__items {
display: flex;
font-size: 48px;
}
.timer__item {
position: relative;
min-width: 60px;
margin-left: 10px;
margin-right: 10px;
padding-bottom: 15px;
text-align: center;
}
.timer__item::before {
content: attr(data-title);
display: block;
position: absolute;
left: 50%;
bottom: 0;
transform: translateX(-50%);
font-size: 14px;
}
.timer__item:not(:last-child)::after {
content: ':';
position: absolute;
right: -15px;
}
Стилизовать таймер обратного отсчета можно так как вы этого хотите.
Вышеприведённый CSS использует flexbox. Знак «:» и текст под каждым компонентом даты выводиться на страницу с помощью псевдоэлементов.
3. Добавить JavaScript:
document.addEventListener('DOMContentLoaded', function() {
// конечная дата, например 1 июля 2021
const deadline = new Date(2021, 06, 01);
// id таймера
let timerId = null;
// склонение числительных
function declensionNum(num, words) {
return words[(num % 100 > 4 && num % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(num % 10 < 5) ? num % 10 : 5]];
}
// вычисляем разницу дат и устанавливаем оставшееся времени в качестве содержимого элементов
function countdownTimer() {
const diff = deadline - new Date();
if (diff <= 0) {
clearInterval(timerId);
}
const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
$days.textContent = days < 10 ? '0' + days : days;
$hours.textContent = hours < 10 ? '0' + hours : hours;
$minutes.textContent = minutes < 10 ? '0' + minutes : minutes;
$seconds.textContent = seconds < 10 ? '0' + seconds : seconds;
$days.dataset.title = declensionNum(days, ['день', 'дня', 'дней']);
$hours.dataset.title = declensionNum(hours, ['час', 'часа', 'часов']);
$minutes.dataset.title = declensionNum(minutes, ['минута', 'минуты', 'минут']);
$seconds.dataset.title = declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
}
// получаем элементы, содержащие компоненты даты
const $days = document.querySelector('.timer__days');
const $hours = document.querySelector('.timer__hours');
const $minutes = document.querySelector('.timer__minutes');
const $seconds = document.querySelector('.timer__seconds');
// вызываем функцию countdownTimer
countdownTimer();
// вызываем функцию countdownTimer каждую секунду
timerId = setInterval(countdownTimer, 1000);
});
4. Установить дату окончания. Например, до 1 июля 2021:
// конечная дата
const deadline = new Date(2021, 06, 01);
Структура кода JavaScript
Основную часть кода занимает функция countdownTimer
:
function countdownTimer() {
// ...
}
Эта функция выполняет расчёт оставшегося времени и обновляет содержимое элементов .timer__item
на странице.
Расчёт оставшегося времени осуществляется посредством вычитания текущей даты из конечной:
// new Date() - текущая дата и время
const diff = deadline - new Date();
Вычисление оставшегося количества дней, часов, минут и секунд выполняется следующим образом:
const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
Встроенная функция Math.floor
используется для округления числа до ближайшего целого (посредством отбрасывания дробной части).
Вывод оставшегося времени на страницу:
$days.textContent = days < 10 ? '0' + days : days;
$hours.textContent = hours < 10 ? '0' + hours : hours;
$minutes.textContent = minutes < 10 ? '0' + minutes : minutes;
$seconds.textContent = seconds < 10 ? '0' + seconds : seconds;
$days.dataset.title = declensionNum(days, ['день', 'дня', 'дней']);
$hours.dataset.title = declensionNum(hours, ['час', 'часа', 'часов']);
$minutes.dataset.title = declensionNum(minutes, ['минута', 'минуты', 'минут']);
$seconds.dataset.title = declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
Переменные $days
, $hours
, $minutes
, $seconds
содержат элементы (таргеты), в которые выводятся компоненты времени.
Изменение содержимого элементов выполняется через textContent
. Если значение меньше 10, то к нему добавляется символ «0».
Получение элементов (выполняется с помощью querySelector
):
// получаем элементы, содержащие компоненты даты
const $days = document.querySelector('.timer__days');
const $hours = document.querySelector('.timer__hours');
const $minutes = document.querySelector('.timer__minutes');
const $seconds = document.querySelector('.timer__seconds');
Функция declensionNum
используется для склонения числительных:
// склонение числительных
function declensionNum(num, words) {
return words[(num % 100 > 4 && num % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(num % 10 < 5) ? num % 10 : 5]];
}
Для постоянного вычисления оставшегося времени и вывода его на страницу используется setInterval
.
Хранение идентификатора таймера осуществляется в переменной timerId
:
// id таймера
let timerId = null;
Использование setInterval
для запуска функции countdownTimer
каждую секунду:
// вызываем функцию countdownTimer каждую 1 секунду
timerId = setInterval(countdownTimer, 1000);
Остановка таймера по истечении времени выполняется в функции countdownTimer
:
function countdownTimer() {
...
if (diff <= 0) {
// останавливаем таймер timerId
clearInterval(timerId);
}
...
}
Скрипт для создания нескольких таймеров отчета на странице
Скрипт, написанный с использованием классов, который можно использовать для создания нескольких таймеров отчета на странице:
// класс для создание таймера обратного отсчета
class CountdownTimer {
constructor(deadline, cbChange, cbComplete) {
this._deadline = deadline;
this._cbChange = cbChange;
this._cbComplete = cbComplete;
this._timerId = null;
this._out = {
days: '', hours: '', minutes: '', seconds: '',
daysTitle: '', hoursTitle: '', minutesTitle: '', secondsTitle: ''
};
this._start();
}
static declensionNum(num, words) => {
return words[(num % 100 > 4 && num % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(num % 10 < 5) ? num % 10 : 5]];
}
_start() {
this._calc();
this._timerId = setInterval(this._calc.bind(this), 1000);
}
_calc() {
const diff = this._deadline - new Date();
const days = diff > 0 ? Math.floor(diff / 1000 / 60 / 60 / 24) : 0;
const hours = diff > 0 ? Math.floor(diff / 1000 / 60 / 60) % 24 : 0;
const minutes = diff > 0 ? Math.floor(diff / 1000 / 60) % 60 : 0;
const seconds = diff > 0 ? Math.floor(diff / 1000) % 60 : 0;
this._out.days = days < 10 ? '0' + days : days;
this._out.hours = hours < 10 ? '0' + hours : hours;
this._out.minutes = minutes < 10 ? '0' + minutes : minutes;
this._out.seconds = seconds < 10 ? '0' + seconds : seconds;
this._out.daysTitle = CountdownTimer.declensionNum(days, ['день', 'дня', 'дней']);
this._out.hoursTitle = CountdownTimer.declensionNum(hours, ['час', 'часа', 'часов']);
this._out.minutesTitle = CountdownTimer.declensionNum(minutes, ['минута', 'минуты', 'минут']);
this._out.secondsTitle = CountdownTimer.declensionNum(seconds, ['секунда', 'секунды', 'секунд']);
this._cbChange ? this._cbChange(this._out) : null;
if (diff <= 0) {
clearInterval(this._timerId);
this._cbComplete ? this._cbComplete() : null;
}
}
}
Пример использования класса CountdownTimer()
для создания таймера на странице:
// 1. Получим элементы в которые нужно вывести оставшееся количество дней, часов, минут и секунд
const elDays1 = document.querySelector('.timer-1 .timer__days');
const elHours1 = document.querySelector('.timer-1 .timer__hours');
const elMinutes1 = document.querySelector('.timer-1 .timer__minutes');
const elSeconds1 = document.querySelector('.timer-1 .timer__seconds');
// 2. Установим время, например, на одну минуту от текущей даты
const deadline1 = new Date(Date.now() + (60 * 1000 + 999));
// 3. Создадим новый объект, используя new CountdownTimer()
new CountdownTimer(deadline1, (timer) => {
elDays1.textContent = timer.days;
elHours1.textContent = timer.hours;
elMinutes1.textContent = timer.minutes;
elSeconds1.textContent = timer.seconds;
elDays1.dataset.title = timer.daysTitle;
elHours1.dataset.title = timer.hoursTitle;
elMinutes1.dataset.title = timer.minutesTitle;
elSeconds1.dataset.title = timer.secondsTitle;
}, () => {
document.querySelector('.timer-1 .timer__result').textContent = 'Таймер завершился!';
});
В new CountdownTimer()
необходимо передать следующие аргументы:
- конечную дату в формате Date;
- функцию, которую нужно выполнять каждую секунду (её, например, можно использовать для обновления содержимого элементов, которые используются для отображения оставшегося времени);
- при необходимости функцию, которую нужно выполнить после завершения таймера.
HTML код первого таймера:
<div class="timer timer-1">
<div class="timer__items">
<div class="timer__item timer__days">00</div>
<div class="timer__item timer__hours">00</div>
<div class="timer__item timer__minutes">00</div>
<div class="timer__item timer__seconds">00</div>
</div>
<div class="timer__result"></div>
</div>
Инициализация остальных таймеров на странице с помощью new CountdownTimer()
выполняется аналогично.
Пример страницы, на которой имеется несколько таймеров обратного отсчёта:

Добрый день. Не понимаю, куда писать вообще эту дату обратного отсчёта
Здравствуйте! Если используете таймер, который реализован через функцию, то конечная дата устанавливается посредством переменной deadline:
Если через использование класса, то так:
const deadline = new Date(2022, 12, 31);
он показывает неверный остаток дней — 54 дня. В чем ошибка?
const deadline = new Date(«2022-12-31 23:59:59»);
пишет 9 дней что осталось. а по факту, там не должно быть больше 7 дней.
Ведь счёчик крутится каждую неделю до четверга 4 утра. А здесь показывает что-то не крректное.
<img
src=«/assets/uploadify/b/d/b/bdb582c39eac28c4fa5a74bbb3492519s.jpg» class=«fancybox thumbnail center»>
И второй вопрос. как зациклить до каждого понедельника до 12:00?
я поставил это. Но вроде, это не правильно
deadline = deadline + (new Date(deadline).getDay() — 11) * 86400000 + 604800000 — (60 * 1000) * 60 + 999;
deadline = new Date(deadline);
deadline.setHours(12, 0, 0, 0);
Подскажите, вынес js код в отдельный файл, как его подключить в HTML коде?
Как подключить JavaScript файл к странице подробно описано здесь.
Нужна Ваша помощь. На своем проекте я использую следующий код таймера:
Данный таймер должен показывать сколько времени осталось до 00:00 и затем возобновлять отсчет (быть зацикленным), но по какой-то причине этого не происходит. Помогите, пожалуйста, разобраться.
Подскажите как зациклить отсчет.
Например время 30 минут и по его окончанию таймер перезапускался и отсчет начинался по новой.
Заранее спасибо.
Например, запустим первый таймер на 10 секунд, а после его завершения ещё один таймер на 10 секунд (открыть)
// конечная дата 28.01.22 12.00
const deadline = (function(y, m, d, h) { return new Date(y, m-1, d, h); })(2022, 01, 28, 12);
Пример вызова:
Нужно просто конечную дату установить на 30 минут больше, чем текущую, ну и убрать ненужный код, связанный с часами и днями (пример).
что-то типа такого:
var deadline = new Date(2021, 08, 11);
deadline.setMonth(deadline.getMonth() — 1);
и ставить уже нормальный месяц.
В любом случае спасибо большое.
Т.е. использовать её вместо этой: