Marquee with CSS and TypeScript: implementation and configuration

A marquee often stutters, breaks the layout, and distracts from the main content. We develop and configure marquee animation turnkey: we select the motion mode, test it on all screens, and hand it over with documentation. Implementation takes from a few days and does not interfere with current tasks.

Development and maintenance of all types of websites:

Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Frequently Asked Questions

Ticker on a website: where marquee animation breaks layout and attention

A ticker almost always starts with a single line of CSS — and almost always ends with the complaint "it jitters on a phone, and on desktop it scrolls too fast." The reason is that marquee animation sets the offset in pixels over a fixed time: content width differs across screens, while the duration stays the same, so the scrolling speed varies by multiples.

On top of that, the classic @keyframes with translateX(-100%) produces a jolt at the loop seam — the text "jumps" back to its starting point, and the eye catches it instantly.

The second group of problems is the conflict with scrolling. A line that moves over a scrolling block intercepts gestures on touch devices, while overflow: hidden on the parent clips dropdown elements and breaks the grid on resize.

If the animation runs on a property that triggers layout recalculation, the browser repaints the layer every frame — on weak devices this means frame rate drops and heating, and on long pages it also competes for the main thread with lazy image loading.

Separately — accessibility and attention. Infinitely moving text interferes with reading adjacent content, disrupts focus during keyboard navigation, and doesn't stop in response to the system "reduce motion" setting.

A user with vestibular sensitivities simply leaves the page, and search engines see text duplication if the line is duplicated for seamlessness.

Let's break down how this is solved: calculating speed from content width, a seamless loop without a jolt, pausing on hover and system settings, moving the animation onto a compositing layer — so the line stays smooth and doesn't take resources away from the rest of the page.

Implementing marquee animation: CSS, JavaScript, and motion modes

A marquee in pure CSS is built on @keyframes with translateX(-50%) and duplicated content: a copy of the strip sits flush against the original, and the cycle loops seamlessly without a jump.

This approach doesn't touch the main thread — the animation moves to compositing, and will-change: transform eliminates unnecessary repaints.

Smoothness is set not by duration but by consistency: linear without pauses gives even motion, and animation-play-state: paused on :hover stops the strip without recalculating position.

When content comes from outside or the strip is assembled dynamically, marquee css gives way to a JavaScript marquee.

Here position is calculated via requestAnimationFrame rather than setInterval: frames sync with the screen refresh rate, and drift doesn't accumulate on weak devices.

We keep speed in pixels per second and convert it to offset based on elapsed time — when frames drop, the strip doesn't "jerk," it just moves more evenly.

Motion modes and their cost

Continuous scrolling is the base mode: one speed, one cycle, predictable load. Ping-pong (the strip reaches the edge and reverses) requires a direction change at the boundary — if not smoothed, a micro-jerk is visible at the turn.

Pause on hover and on keyboard focus is mandatory for accessibility: motion is disabled via prefers-reduced-motion, and the strip remains readable in a static state.

Variant When it fits Limitations
CSS @keyframes + duplicated strip A static set of logos, a simple ticker Content is fixed at the layout stage, hard to change speed on the fly
JavaScript + requestAnimationFrame Dynamic data, varying speed, pause on events Requires control over frame cleanup on unmount
Hybrid: CSS animation driven by variables Need CSS smoothness and configuration flexibility Requires careful synchronization of CSS variables with state

What it delivers

On a long strip of dozens of elements, moving to compositing and requestAnimationFrame removes frame drops during page scrolling: motion stops competing with the main thread.

A strip of a hundred logos maintains even motion, and pause on hover plus disabling via prefers-reduced-motion cover accessibility requirements without a separate implementation.

For frame management and synchronization with markup in projects, we use requestAnimationFrame — it provides predictable timing instead of timers.

How we implement a marquee: from audit to handover

Implementing a marquee animation starts with an audit of the current markup: we look at what the block is built from, whether there are fixed widths, how the container behaves on overflow, and whether the new ticker conflicts with existing transforms and overflow.

At this stage we determine where animation is acceptable under accessibility requirements and where it will have to be disabled or replaced with a static block — that is cheaper than redoing it after release.

Next, we design the motion scheme: we choose between a CSS animation with duplicated content for a seamless loop and control via TypeScript when we need pause on hover, adaptive speed, or synchronization with scrolling.

Separately, we calculate the track length and the number of copies so that no gaps appear on wide screens and the ticker does not "jitter" on narrow ones due to width recalculation.

  1. Audit of markup and content — analyzing the block structure, checking overflows and conflicts with styles.
  2. Designing the animation scheme — choosing the approach, calculating the track length and the number of content duplicates.
  3. Setting up the marquee — tying speed to container width, pause on hover and focus.
  4. Accessibility considerations — disabling motion under prefers-reduced-motion, preserving text readability.
  5. Testing on devices — running on mobile, tablets, and desktop, including screen orientation changes.
  6. Rendering optimization — moving the animation to a compositor layer so the ticker does not trigger layout recalculation.
  7. Handover and documentation — configuration parameters, instructions for adjusting speed and ticker content.

This sequence eliminates typical failures: stuttering on low-end devices, the ticker breaking when the window width changes, and the animation "sticking" after returning to the tab.

Instead of fixes prompted by complaints, the client gets predictable block behavior across the entire device fleet. Describe your task — we will get back to you with an estimate and a work plan.

How is a CSS animation different from a JavaScript marquee implementation?

A CSS marquee animation lives entirely in the browser's rendering engine: you define keyframes and animation-play-state, and the compositor calculates the element offset, bypassing the main thread.

As long as the marquee doesn't change its content, the page doesn't recalculate layout or repaint layers — with a dozen such blocks on a page, this is noticeable in scroll stability.

The limitation is the same: CSS doesn't know how much space the content takes up, so a seamless loop is built on duplicating the track and translateX(-50%), and pausing on hover or focus is done only via :hover and :focus-within.

A JavaScript implementation controls the animation from code: the position is calculated in requestAnimationFrame, the offset is written to transform, and speed, direction, and starting point are just variables.

This provides what CSS lacks: stopping at a specific element, synchronizing multiple tracks, adjusting speed to text length after data loads, pausing when the tab goes to the background via visibilitychange.

The price is a loop on the main thread: if heavy work is happening nearby, frames drop, and with careless writes to left or top instead of transform, the browser recalculates layout on every frame.

The choice of marquee implementation comes down to the scenario. A static set of logos or a text ticker without interactivity — CSS: less code, zero load on the thread, works with scripts disabled.

A feed with data from an API, elements of varying length, click-to-stop, and coupling with other blocks — JavaScript, because controlling the animation requires access to state, not just styles.

A hybrid covers both cases: CSS handles the markup and basic motion, while a script intervenes selectively — setting animation-play-state: paused on hover, recalculating duration after content loads, disabling motion under prefers-reduced-motion. This way the main loop stays on the compositor, while the logic stays in code.

Case study: how a marquee stopped jittering and loading the page

A client came with a typical complaint: the marquee on the home page "jitters" on weak laptops and old phones, and when the tab is opened in the background the browser loads the CPU to noticeable heating.

Measurements confirmed the diagnosis: the animation ran via setInterval with position recalculation in JavaScript, every 16 ms offsetWidth was read and style.left was written — this caused forced layout synchronization on every frame.

On a weak device the interval could not keep up, frames were dropped, and the ticker visually caught up to the position in jerks.

What was changed

The movement was moved to the compositor layer: animation via transform: translate3d() with CSS keyframes, and JS was left only for control — pausing on hover, speed adjustment, and restart.

The duration is set by a variable rather than recalculated in a loop, so the browser drives the ticker itself, without involving the main thread. Content duplication for seamlessness was done via an aria-hidden copy so that the screen reader does not read the text twice.

prefers-reduced-motion was added: with the system setting "reduce motion" the ticker stops and turns into a regular scrollable area. Pausing via visibilitychange mutes the animation in an inactive tab — this removed the heating and extra battery drain.

Before After
Position recalculated in JS every frame CSS animation on the compositor
Jerks on weak devices Smooth movement, stable speed
Heating and battery drain in the background Animation pauses outside the tab
Text is read twice Copy is hidden from screen readers

Result

After the fixes, the frame rate on a weak device leveled out and stopped dropping, the CPU load at rest decreased by roughly three times, and in a background tab — almost to zero.

The ticker speed is now the same on all devices, because it is set by the traversal time, not by the repaint rate. The fixes took one work cycle and did not require changing the page markup.

The approach relies on standard browser mechanisms, so it does not break with updates. Implementation details were checked against the MDN Web Docs documentation on CSS animations and compositing.

Concerns before implementation: compatibility, rollback, and access

What if the marquee conflicts with the current markup? The marquee animation is almost always isolated in a separate layer: a container with overflow: hidden, a track driven by transforms, and content duplication for a seamless loop.

Such a block does not touch the page grid, does not affect the document flow, and does not break existing components — animation compatibility is checked in a targeted way, without rebuilding the layout.

How are changes rolled back if something goes wrong? Each edit goes in as a separate commit with a description, styles and script are moved into isolated files rather than spread across the project.

Rolling back changes means reverting a single commit, not manually untangling someone else's code: the previous version of the block is restored within minutes.

Who gets development access, and how? We work through separate accounts with the minimum required permissions, without access to payment and personal data. Development access is granted for the duration of the work and revoked upon completion — this is recorded in the handover.

Will the animation lag on low-end devices?

The motion is built on transforms and requestAnimationFrame, not on recalculating position every frame. With prefers-reduced-motion, the marquee stops automatically — this is an accessibility requirement, not an option. On low-end devices, the load stays within a single composited layer.

After delivery, the client receives:

  • the block's source code with comments and file structure;
  • configuration of speed, direction, and pause on hover;
  • a diagram for connecting to the current template and build;
  • accessibility rules and behavior under reduced-motion;
  • instructions for editing text and adding new elements;
  • a checklist for verification after content updates;
  • a description of the procedure for rolling back to the previous version.

Describe your task and current stack — we'll get back to you with an estimate and a work plan for the marquee.

Timeline for implementing a marquee by stages

The timeline depends not on the marquee animation itself — its mechanics take hours — but on how much time goes into content approval, environment access, and testing on real data.

Below is an approximate development plan, which we refine after reviewing the task: the figures show the order of work and the points where waiting on the client's side usually occurs.

Content work runs in parallel: if the marquee pulls data from an external source, additional time is added for agreeing on the format and handling failures.

At the testing stage, we separately look at how the marquee animation behaves when the text is many times wider than the screen, and when there is almost none — these are the two most common cases where the prototype looks good but the layout breaks in production.

The general guideline for a typical task is from one week to two and a half, if integration with third-party systems is not required. We give the exact implementation timeline after we see your page and understand where the text comes from. Describe your task — we will get back to you with an estimate and a stage-by-stage plan.

Our competencies:

Latest works

  • B2B ADVANCE company website development
    B2B ADVANCE company website development
    1542
  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1394
  • Website development for BELFINGROUP
    Website development for BELFINGROUP
    1081
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1369
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1142
  • Website development for FIXPER company
    Website development for FIXPER company
    1060