Бегущая строка (marquee) на CSS и TypeScript: реализация и настройка

Бегущая строка часто дёргается, ломает вёрстку и отвлекает от главного. Мы разрабатываем и настраиваем marquee-анимацию под ключ: подбираем режим движения, проверяем на всех экранах и передаём с документацией. Внедрение занимает от нескольких дней и не мешает текущим задачам.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Бегущая строка (marquee) на CSS и TypeScript: реализация и настройка
Простой
~1 день
Часто задаваемые вопросы

Бегущая строка на сайте: где marquee анимация ломает вёрстку и внимание

Бегущая строка почти всегда начинается с одной строки CSS — и почти всегда заканчивается жалобой «на телефоне дёргается, а на десктопе уезжает слишком быстро». Причина в том, что marquee анимация задаёт смещение в пикселях за фиксированное время: ширина контента на разных экранах разная, а длительность одна, поэтому скорость плавания меняется в разы. Плюс классический @keyframes со translateX(-100%) даёт рывок на стыке цикла — текст «прыгает» в исходную точку, и глаз это ловит мгновенно.

Вторая группа проблем — конфликт с прокруткой. Строка, которая двигается поверх скроллящегося блока, перехватывает жесты на тач-устройствах, а overflow: hidden на родителе обрезает выпадающие элементы и ломает сетку при ресайзе. Если анимация запущена на свойстве, вызывающем пересчёт раскладки, браузер перерисовывает слой каждый кадр — на слабых устройствах это просадка частоты и нагрев, а на длинных страницах ещё и борьба за основной поток с ленивой загрузкой картинок.

Отдельно — доступность и внимание. Бесконечно движущийся текст мешает читать соседний контент, сбивает фокус при навигации с клавиатуры и не останавливается по системной настройке «уменьшить движение». Пользователь с вестибулярными особенностями просто уходит со страницы, а поисковые системы видят дублирование текста, если строка продублирована для бесшовности.

Разбираем, как это закрывается: расчёт скорости от ширины контента, бесшовный цикл без рывка, пауза по наведению и системным настройкам, вынос анимации на композиционный слой — чтобы строка оставалась плавной и не забирала ресурсы у остальной страницы.

Реализация marquee анимации: CSS, JavaScript и режимы движения

Бегущая строка на чистом CSS собирается на @keyframes со translateX(-50%) и дублированном контенте: копия ленты встаёт вплотную к оригиналу, и цикл замыкается без рывка. Такой вариант не трогает главный поток — анимация уходит в композитинг, а will-change: transform снимает лишние перерисовки. Плавность задаётся не длительностью, а согласованностью: linear без пауз даёт равномерное движение, а animation-play-state: paused на :hover останавливает ленту без пересчёта позиции.

Когда контент приходит извне или лента собирается динамически, marquee css уступает место бегущей строке на JavaScript. Здесь позиция считается через requestAnimationFrame, а не через setInterval: кадры синхронизируются с частотой обновления экрана, и на слабых устройствах не копится дрейф. Скорость держим в пикселях в секунду и переводим в смещение по прошедшему времени — при просадке кадров лента не «дёргается», а просто идёт ровнее.

Режимы движения и их цена

Непрерывная прокрутка — базовый режим: одна скорость, один цикл, предсказуемая нагрузка. Пинг-понг (лента доходит до края и разворачивается) требует смены направления на границе — если не сгладить, на развороте видно микрорывок. Пауза по наведению и по фокусу с клавиатуры — обязательна для доступности: движение отключается через prefers-reduced-motion, а лента остаётся читаемой статично.

Вариант Когда подходит Ограничения
CSS @keyframes + дубль ленты Статичный набор логотипов, простой тикер Контент фиксирован на этапе вёрстки, сложно менять скорость на лету
JavaScript + requestAnimationFrame Динамические данные, разная скорость, пауза по событиям Нужен контроль за очисткой кадров при размонтировании
Гибрид: CSS-анимация, управляемая переменными Нужна плавность CSS и гибкость настроек Требует аккуратной синхронизации CSS-переменных с состоянием

Что даёт на выходе

На длинной ленте из десятков элементов переход на композитинг и requestAnimationFrame убирает просадки кадров при прокрутке страницы: движение перестаёт конкурировать с основным потоком. Лента из сотни логотипов сохраняет ровный ход, а пауза по наведению и отключение по prefers-reduced-motion закрывают требования доступности без отдельной реализации.

Для управления кадрами и синхронизации с разметкой в проектах используем requestAnimationFrame — он даёт предсказуемый тайминг вместо таймеров.

Как мы внедряем бегущую строку: от аудита до передачи

Внедрение marquee-анимации начинается с аудита текущей вёрстки: смотрим, из чего собран блок, есть ли фиксированные ширины, как ведёт себя контейнер при переполнении и не конфликтует ли новая лента с существующими трансформациями и overflow. На этом этапе фиксируем, где анимация допустима по требованиям доступности, а где её придётся отключать или заменять статичным блоком — это дешевле, чем переделывать после релиза.

Дальше проектируем схему движения: выбираем между CSS-анимацией с дублированием контента для бесшовного цикла и управлением через TypeScript, когда нужны пауза при наведении, адаптивная скорость или синхронизация с прокруткой. Отдельно считаем длину трека и число копий, чтобы на широких экранах не появлялось пустот, а на узких лента не «дёргалась» из-за пересчёта ширины.

  1. Аудит вёрстки и контента — разбор структуры блока, проверка переполнений и конфликтов со стилями.
  2. Проектирование схемы анимации — выбор подхода, расчёт длины трека и количества дублей контента.
  3. Настройка бегущей строки — привязка скорости к ширине контейнера, пауза при наведении и фокусе.
  4. Учёт доступности — отключение движения при prefers-reduced-motion, сохранение читаемости текста.
  5. Проверка на устройствах — прогон на мобильных, планшетах и десктопе, включая смену ориентации экрана.
  6. Оптимизация отрисовки — вынос анимации на композиторный слой, чтобы лента не вызывала перерасчёт макета.
  7. Передача и документация — параметры настройки, инструкция по правке скорости и состава ленты.

Такая последовательность убирает типовые сбои: рывки на слабых устройствах, обрыв ленты при смене ширины окна и «залипание» анимации после возврата на вкладку. Вместо правок по факту жалоб заказчик получает предсказуемое поведение блока на всём парке устройств. Опишите задачу — вернёмся с оценкой и планом работ.

Чем CSS-анимация отличается от JavaScript-реализации бегущей строки?

CSS-анимация бегущей строки живёт целиком в браузерном движке отрисовки: вы задаёте ключевые кадры и animation-play-state, а смещение элементов считает композитор, минуя основной поток. Пока строка не меняет содержимое, страница не пересчитывает разметку и не перерисовывает слои — при десятке таких блоков на странице это заметно по стабильности прокрутки. Ограничение в том же: CSS не знает, сколько места занимает контент, поэтому бесшовный цикл строится на дублировании дорожки и translateX(-50%), а пауза по наведению или фокусу делается только через :hover и :focus-within.

JavaScript-реализация управляет анимацией из кода: позиция считается в requestAnimationFrame, смещение пишется в transform, а скорость, направление и точка старта — обычные переменные. Это даёт то, чего нет у CSS: остановку на конкретном элементе, синхронизацию нескольких дорожек, подстройку скорости под длину текста после загрузки данных, паузу при уходе вкладки в фон через visibilitychange. Плата — цикл на основном потоке: если рядом идёт тяжёлая работа, кадры проседают, а при неаккуратной записи в left или top вместо transform браузер пересчитывает разметку на каждом кадре.

Выбор реализации бегущей строки упирается в сценарий. Статичный набор логотипов или текстовый тикер без интерактива — CSS: меньше кода, нулевая нагрузка на поток, работает при отключённых скриптах. Лента с данными из API, разной длиной элементов, остановкой по клику и связкой с другими блоками — JavaScript, потому что управление анимацией требует доступа к состоянию, а не только к стилям.

Гибрид закрывает оба случая: разметку и базовое движение задаёт CSS, а скрипт вмешивается точечно — ставит animation-play-state: paused при наведении, пересчитывает длительность после подгрузки контента, отключает движение при prefers-reduced-motion. Так основной цикл остаётся на композиторе, а логика — в коде.

Кейс: как бегущая строка перестала дёргаться и нагружать страницу

Клиент пришёл с типовой жалобой: бегущая строка на главной «дёргается» на слабых ноутбуках и старых телефонах, а при открытии вкладки в фоне браузер грузит процессор до заметного нагрева. Замеры подтвердили диагноз: анимация шла через setInterval с пересчётом позиции в JavaScript, каждые 16 мс читался offsetWidth и записывался style.left — это вызывало принудительную синхронизацию раскладки на каждом кадре. На слабом устройстве интервал не успевал отработать, кадры пропускались, и лента визуально рывками догоняла позицию.

Что изменили

Перевели движение на композиторный слой: анимация через transform: translate3d() с ключевыми кадрами CSS, а JS оставили только на управление — паузу при наведении, подстройку скорости и перезапуск. Длительность задаётся переменной, а не пересчётом в цикле, поэтому браузер ведёт ленту сам, без участия основного потока. Дублирование контента для бесшовности сделали через aria-hidden-копию, чтобы скринридер не читал текст дважды.

Добавили prefers-reduced-motion: при системной настройке «меньше движения» лента останавливается и превращается в обычную прокручиваемую область. Пауза по visibilitychange глушит анимацию в неактивной вкладке — это убрало нагрев и лишний расход батареи.

Было Стало
Пересчёт позиции в JS каждый кадр CSS-анимация на композиторе
Рывки на слабых устройствах Ровное движение, стабильная скорость
Нагрев и расход батареи в фоне Анимация встаёт на паузу вне вкладки
Текст читается дважды Копия скрыта от скринридеров

Результат

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

Подход опирается на стандартные механизмы браузера, поэтому не ломается при обновлениях. Детали реализации сверяли с документацией MDN Web Docs по CSS-анимациям и композитингу.

Сомнения перед внедрением: совместимость, откат и доступы

Что если бегущая строка конфликтует с текущей вёрсткой? Marquee-анимация почти всегда изолируется в отдельный слой: контейнер с overflow: hidden, трек на трансформациях, дублирование контента для бесшовного цикла. Такой блок не трогает сетку страницы, не влияет на поток документа и не ломает существующие компоненты — совместимость анимации проверяется точечно, без пересборки макета.

Как откатываются изменения, если что-то пойдёт не так? Каждая правка идёт отдельным коммитом с описанием, стили и скрипт выносятся в изолированные файлы, а не размазываются по проекту. Откат изменений — это возврат одного коммита, а не ручная распутывание чужого кода: предыдущая версия блока возвращается за минуты.

Кто и как получает доступы для разработки? Мы работаем через отдельные учётные записи с минимально нужными правами, без доступа к платёжным и персональным данным. Доступы для разработки выдаются на время работ и отзываются по завершении — это фиксируется в передаче.

Анимация будет тормозить на слабых устройствах?

Движение строится на трансформациях и requestAnimationFrame, а не на пересчёте позиции в каждом кадре. При prefers-reduced-motion бегущая строка останавливается автоматически — это требование доступности, а не опция. На слабых устройствах нагрузка остаётся в пределах одного композитного слоя.

После сдачи заказчик получает на руки:

  • исходный код блока с комментариями и структурой файлов;
  • конфигурацию скорости, направления и паузы при наведении;
  • схему подключения к текущему шаблону и сборке;
  • правила доступности и поведение при reduced-motion;
  • инструкцию по правке текста и добавлению новых элементов;
  • чеклист проверки после обновления контента;
  • описание процедуры отката к предыдущей версии.

Опишите вашу задачу и текущий стек — вернёмся с оценкой и планом работ по бегущей строке.

Сроки внедрения бегущей строки по этапам

Сроки зависят не от самой marquee анимации — её механика занимает часы, — а от того, сколько времени уходит на согласование контента, доступы к среде и проверку на реальных данных. Ниже — ориентировочный план разработки, который мы уточняем после разбора задачи: цифры показывают порядок работ и точки, где обычно появляется ожидание на стороне заказчика.

Параллельно идёт работа с контентом: если строка тянет данные из внешнего источника, добавляется время на согласование формата и обработку сбоев. На этапе проверки мы отдельно смотрим, как ведёт себя marquee анимация, когда текста больше ширины экрана в разы, и когда его почти нет — это два самых частых случая, где прототип выглядит хорошо, а на проде ломается вёрстка.

Общий ориентир для типовой задачи — от недели до двух с половиной, если не требуется интеграция со сторонними системами. Точные сроки внедрения называем после того, как увидим вашу страницу и поймём, откуда берётся текст. Опишите задачу — вернёмся с оценкой и планом по этапам.

Наши компетенции:

Последние работы

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1142
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060