Topics
Recent articles

Build a Lightweight CSS Marquee Without Damaging Web Vitals

A guide to building a pure CSS infinite marquee that achieves 60fps hardware acceleration, maintains zero Cumulative Layout Shift, and preserves accessibility without JavaScript.

Table of Contents8 sections
A laptop screen showing a code editor with visible programming code in a dimly lit environment.
A laptop screen showing a code editor with visible programming code in a dimly lit environment.

Infinite tickers and scrolling marquees are a frequent requirement for showcasing partner logos, engineering badges, or featured announcements on modern marketing sites. Yet, many implementations rely on third-party JavaScript libraries or heavy animation wrappers that degrade performance. When a marquee is driven by JavaScript style updates on every frame, it blocks the main thread, inflates Total Blocking Time, and triggers costly layout recalculations. Developers need a way to create continuous visual movement that remains buttery smooth without sacrificing user experience or performance scores. For a related implementation, see App Updates Play Vs Managed Devices.

The Performance Cost of JavaScript Marquees

Traditional ticker scripts rely on requestAnimationFrame loops or timer intervals to mutate element positions on every tick. This approach forces the browser to recalculate styles and geometry during the layout phase for every active frame. On mobile devices or lower-powered hardware, this constant recalculation drops frame rates below sixty frames per second and elevates Total Blocking Time. Furthermore, dynamic DOM node insertion during script initialization can trigger sudden content jumps, ruining Cumulative Layout Shift metrics before the page fully settles. For a related implementation, see Memory Optimization Low Ram Devices.

The Double-Track Duplication Pattern

To achieve a seamless infinite loop without JavaScript calculations, you can structure the HTML with a parent container and two identical track children. Each track contains the exact same sequence of items. When the container width is set to fit the content of a single track, duplicating that track ensures that as the first set of items scrolls completely out of view, the second set seamlessly takes its place.

<div class="marquee-container">
  <div class="marquee-track">
    <div class="marquee-group">
      <span>Acme Corp</span>
      <span>Beta LLC</span>
      <span>Gamma Inc</span>
    </div>
    <div class="marquee-group" aria-hidden="true">
      <span>Acme Corp</span>
      <span>Beta LLC</span>
      <span>Gamma Inc</span>
    </div>
  </div>
</div>

Setting the second group with aria-hidden="true" ensures that screen readers do not read the duplicated items twice, preserving a clean accessibility tree.

GPU Compositing with 3D Transforms

Performance relies entirely on choosing the right CSS properties to animate. Animating layout properties like margin-left or left forces the browser to repeat layout and paint steps continuously. By contrast, using hardware-accelerated transforms shifts the workload entirely to the GPU compositor thread.

.marquee-container {
  overflow: hidden;
  width: 100%;
  display: flex;
}

.marquee-track {
  display: flex;
  width: max-content;
  animation: scroll-marquee 30s linear infinite;
}

.marquee-group {
  display: flex;
  gap: 2rem;
  justify-content: space-around;
  min-width: 100%;
}

@keyframes scroll-marquee {
  0% {
    transform: translate3d(0, 0, 0);
  }
  100% {
    transform: translate3d(-50%, 0, 0);
  }
}
}

Because the track contains two identical groups side by side, translating the entire track by negative fifty percent moves exactly one full group width before looping back to zero instantly and invisibly.

Zero CLS Containment

Layout shifts often occur when dynamic components load fonts or images after initial render. To prevent the marquee container from causing layout instability during hydration, enforce strict CSS containment. By applying explicit height constraints and sizing properties to the container, the browser reserves the exact layout box ahead of time.

.marquee-container {
  contain: layout size;
  height: 4rem;
}

This containment rule tells the optimization engine that the internal layout of the marquee does not affect outside document elements, eliminating unexpected reflows during load.

Polishing with CSS Edge Masks

Fading out the left and right edges of a scrolling marquee provides a polished visual finish without adding extra structural DOM nodes or overlapping gradient overlays. The mask-image property applies a linear alpha gradient directly to the element rendering surface.

.marquee-container {
  mask-image: linear-gradient(
    to right,
    transparent,
    black 15%,
    black 85%,
    transparent
  );
}

This composited mask ensures that items fade smoothly into view at the container boundaries, adapting cleanly to any background color or theme.

Accessibility and User Control

Continuous motion can cause discomfort for users with vestibular disorders. Providing clear ways to pause or disable the animation is both an ethical necessity and a requirement for strict accessibility compliance. You can pause movement on hover or keyboard focus, and completely disable it for users who prefer reduced motion.

.marquee-container:hover .marquee-track,
.marquee-container:focus-within .marquee-track {
  animation-play-state: paused;
}

@media (prefers-reduced-motion: reduce) {
  .marquee-track {
    animation: none;
    transform: none;
    overflow-x: auto;
  }
}

By adding these rules, users retain full control over their reading experience, and keyboard navigators can interact with the content inside the ticker without struggling against moving targets.

Conclusion

Implementing an infinite ticker no longer requires heavy JavaScript plugins or complex timer loops. By combining a double-track flexbox structure, GPU-accelerated transforms, CSS edge masks, and strict accessibility safeguards, you can deliver smooth visual motion that protects Core Web Vitals and runs efficiently across all devices.

Continue Exploring

You Might Also Like

View all articles
Fail-Closed Static Distribution Verification
5 min read

Fail-Closed Static Distribution Verification

Learn how to build a zero-dependency post-build verification script that inspects static site output files for private data leaks and corrupted assets before deployment.

Isolating Publisher Integrations in Workflows
3 min read

Isolating Publisher Integrations in Workflows

Learn how to isolate optional third-party publishing integrations from a canonical serverless workflow to protect resource budgets and accurately track distribution states.