Перейти к содержанию
Инструкция

Счётчик обратного отсчёта в «Списке новостей» Битрикса

Как вывести ближайшее мероприятие компонентом «Список новостей» и повесить на него таймер обратного отсчёта, взяв дату из свойства элемента. Дату отдаём в JS через data-атрибут, а сам счётчик пишем на чистом JavaScript без jQuery.

Обновлено 22 июля 8 минут чтения

Задача: вывести ближайшее событие компонентом «Список новостей» и показать под ним таймер «до старта осталось 3 дня 4 часа». Дату события берём из свойства элемента, а сам отсчёт – на чистом JavaScript, без внешней библиотеки. Раньше для этого подключали jQuery.countdown, но в 2026 году отдельная библиотека и сам jQuery ради одного таймера уже избыточны.

Шаг 1. Свойство и настройка компонента

В инфоблоке «Мероприятия» создаём свойство «Дата мероприятия» типа «Дата/время» с кодом TIME_EVENT – из него таймер возьмёт дедлайн. Дальше настраиваем компонент bitrix:news.list:

  • количество элементов на странице – 1 (нужно ближайшее событие);
  • сортировка – по дате начала активности или по свойству TIME_EVENT, чтобы «ближайшее» было первым;
  • в блоке «Источник данных» отмечаем свойство TIME_EVENT, иначе оно не попадёт в DISPLAY_PROPERTIES.

Шаг 2. Отдаём дату в HTML через data-атрибут

Копируем шаблон компонента в свой шаблон сайта. В нём переводим значение свойства в Unix-timestamp через MakeTimeStamp() и кладём его в data-атрибут блока таймера. Timestamp – самый надёжный способ передать момент времени в JavaScript: он не зависит от формата даты и локали.

<?php foreach ($arItem['DISPLAY_PROPERTIES'] as $pid => $arProperty): ?>
    <?php if ($pid === 'TIME_EVENT'): ?>
        <?php $eventTs = MakeTimeStamp($arProperty['VALUE']); ?>
        <div class="event__date">
            <?= FormatDate('d F Y в H:i', $eventTs) ?> <?php // читаемая дата для человека ?>
        </div>
        <!-- дедлайн для JS: timestamp в миллисекундах -->
        <div class="event__counter" data-deadline="<?= $eventTs * 1000 ?>"></div>
    <?php endif ?>
<?php endforeach ?>

Здесь MakeTimeStamp переводит строку из свойства в timestamp (секунды), а * 1000 даёт миллисекунды – именно в них работает Date в JavaScript. Заодно выводим человеку понятную дату через FormatDate('d F Y в H:i', ...).

Шаг 3. Таймер на чистом JavaScript

В отдельном JS-файле забираем дедлайн из data-атрибута и раз в секунду пересчитываем остаток. Никакого jQuery – только современный синтаксис (const/let, стрелочные функции):

const box = document.querySelector('.event__counter');

if (box) {
  const deadline = Number(box.dataset.deadline);

  // склонение: plural(5, ['день','дня','дней']) → 'дней'
  const plural = (n, forms) => {
    const idx = (n % 100 > 4 && n % 100 < 20)
      ? 2
      : [2, 0, 1, 1, 1, 2][Math.min(n % 10, 5)];
    return forms[idx];
  };

  const render = () => {
    const diff = deadline - Date.now();

    if (diff <= 0) {
      box.textContent = 'Событие началось';
      clearInterval(timer);
      return;
    }

    const totalSec = Math.floor(diff / 1000);
    const days = Math.floor(totalSec / 86400);
    const hours = Math.floor((totalSec % 86400) / 3600);
    const mins = Math.floor((totalSec % 3600) / 60);
    const secs = totalSec % 60;

    box.textContent =
      `${days} ${plural(days, ['день', 'дня', 'дней'])} ` +
      `${hours} ${plural(hours, ['час', 'часа', 'часов'])} ` +
      `${mins} ${plural(mins, ['минута', 'минуты', 'минут'])} ` +
      `${secs} ${plural(secs, ['секунда', 'секунды', 'секунд'])}`;
  };

  render();
  const timer = setInterval(render, 1000);
}

Почему именно так

  • Считаем от Date.now(), а не накапливаем. Каждый тик берёт свежую разницу «дедлайн − сейчас», поэтому таймер не «плывёт», даже если вкладка была свёрнута или браузер притормозил интервалы.
  • Останавливаемся на нуле. При diff <= 0 вызываем clearInterval, иначе счётчик уйдёт в отрицательные значения.
  • Склонение по русским правилам. Функция plural выбирает форму «день / дня / дней» по последней цифре и исключению для 11–14.

Подводные камни

  • Часовой пояс. Unix-timestamp не зависит от пояса, но MakeTimeStamp трактует строку свойства в поясе сайта. Если сервер и посетитель в разных поясах, договоритесь, что дедлайн задаётся во времени сайта, и не смешивайте это с локальным временем браузера.
  • Кэш компонента. Дата попадает в кэшируемый шаблон как timestamp – это правильно: кэшируется момент, а не «осталось столько-то». Сам отсчёт всегда живой, потому что считается на клиенте.
  • Свойство не выводится. Если DISPLAY_PROPERTIES пуст, значит свойство не отмечено в «Источнике данных» настроек компонента – проверьте настройки, это самая частая причина «пустого» таймера.
  • Одна дата – один блок. Скрипт написан под один .event__counter. Для нескольких таймеров на странице оберните логику в querySelectorAll(...).forEach(...), чтобы у каждого был свой дедлайн.

Тот же приём для баннера акции без инфоблока – в гайде «Скрипт отсчёта времени до конца акции». Про форматирование дат из свойств – «Сменить формат даты в CMS Битрикс» и «Формат Ydiff». Как вывести конкретное свойство элемента – «Как вывести определённое поле элемента инфоблока».

Частые вопросы

Как передать дату из свойства Битрикса в JavaScript-таймер?

Переведите значение свойства в Unix-timestamp через MakeTimeStamp, умножьте на 1000 и положите в data-атрибут блока. В JS заберите его через element.dataset и создайте счётчик – timestamp не зависит от формата даты и локали.

Нужен ли jQuery для счётчика обратного отсчёта?

Нет. В 2026 году таймер пишется на чистом JavaScript в несколько строк с setInterval и Date.now(). Отдельная библиотека вроде jQuery.countdown и сам jQuery ради одного счётчика избыточны.

Почему таймер показывает пустое значение?

Чаще всего свойство даты не отмечено в разделе «Источник данных» настроек компонента, поэтому оно не попадает в DISPLAY_PROPERTIES. Проверьте настройки news.list.

Как сделать правильное склонение «3 дня» / «5 дней»?

Используйте функцию plural, которая по последней цифре числа и исключению для 11–14 выбирает нужную форму из массива ['день','дня','дней'].

Почему счётчик уходит в минус после начала события?

Не остановлен интервал. Когда разница deadline − Date.now() становится

Валентина Меланина

Хотите обсудить свой проект?

Помогу с разработкой, аналитикой и AI-видимостью вашего сайта

Если у вас есть задача — от внедрения разметки и аналитики до полной переработки сайта — напишите, обсудим объём и подход.