Tech

CSS Tips

How to Create Seamless Scrolling Text with CSS

A CSS-only technique for creating infinite loop scrolling text, perfect for news tickers and decorative elements.

Coding css animation

Introduction

Horizontally scrolling text is used in various contexts: news tickers, announcement banners, and decorative design accents.

The HTML <marquee> tag used to handle this, but it's now deprecated. This article introduces how to implement smoothly looping text that never breaks using CSS keyframe animations.

Completed Demo

Here's the completed animation. The text scrolls smoothly in an endless loop without any breaks.

Preview
This text scrolls horizontally across the screen.This text scrolls horizontally across the screen.
HTML
<div style="width:100%;overflow:hidden;"><div style="display:flex;width:max-content;animation:marquee-demo 8s linear infinite;"><span style="flex-shrink:0;white-space:nowrap;font-size:1.5rem;font-weight:600;padding-right:3rem;">This text scrolls horizontally across the screen.</span><span style="flex-shrink:0;white-space:nowrap;font-size:1.5rem;font-weight:600;padding-right:3rem;">This text scrolls horizontally across the screen.</span></div></div>
CSS
@keyframes marquee-demo { 0% { transform: translateX(0); } 100% { transform: translateX(-50%); } }

How It Works

The key to this technique is placing two identical texts side by side and looping them.

1. **Duplicate the text**
Place two identical text elements next to each other horizontally.

2. **Use Flexbox for horizontal layout**
Set the wrapper to display: flex to align the text elements in a row.

3. **Move by -50%**
Since there are two identical texts, moving by -50% returns to the same visual state. This creates the seamless loop.

HTML Code

<div class="marquee">
  <div class="marquee__wrapper">
    <span class="marquee__text">This text scrolls horizontally.</span>
    <span class="marquee__text">This text scrolls horizontally.</span>
  </div>
</div>

CSS Code

.marquee {
  overflow: hidden;
}

.marquee__wrapper {
  display: flex;
  animation: marquee-scroll 10s linear infinite;
}

.marquee__text {
  flex-shrink: 0;
  white-space: nowrap;
  padding-right: 2rem; /* Gap between texts */
}

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

Role of Each Property

overflow: hidden

Hides text that overflows the container. This ensures scrolling text disappears when it moves outside the visible area.

display: flex

Uses Flexbox to arrange child elements (spans) horizontally in a row.

flex-shrink: 0

Prevents flex items from shrinking. Without this, the text would be compressed.

white-space: nowrap

Keeps the text on a single line without wrapping.

translateX(-50%)

With two identical texts side by side, moving 50% returns to the same visual state, creating a continuous loop.

linear

Setting animation-timing-function to linear ensures the text flows at a constant speed.

Customization

This animation is easily customizable.

**To change the speed**
Modify the duration in the animation property. Smaller values make it faster, larger values make it slower.

**To reverse the direction**
Change translateX to a positive value (50%) and set the initial position to -50%.

**To pause on hover**
Add .marquee:hover .marquee__wrapper { animation-play-state: paused; }

Reverse Direction Variation

By reversing the translateX values, you can make the text flow from left to right instead of right to left.

Preview
This text flows from left to right.This text flows from left to right.
HTML
<div style="width:100%;overflow:hidden;"><div style="display:flex;width:max-content;animation:marquee-demo-reverse 8s linear infinite;"><span style="flex-shrink:0;white-space:nowrap;font-size:1.5rem;font-weight:600;padding-right:3rem;">This text flows from left to right.</span><span style="flex-shrink:0;white-space:nowrap;font-size:1.5rem;font-weight:600;padding-right:3rem;">This text flows from left to right.</span></div></div>
CSS
@keyframes marquee-demo-reverse { 0% { transform: translateX(-50%); } 100% { transform: translateX(0); } }

Accessibility Considerations

Moving content can cause discomfort or distraction for some users.

Using the prefers-reduced-motion media query, you can stop the animation when users have enabled "reduce motion" in their system settings.

Accessibility-Friendly CSS

@media (prefers-reduced-motion: reduce) {
  .marquee__wrapper {
    animation: none;
  }
}

Summary

Using CSS keyframe animations, you can implement seamless scrolling text without JavaScript.

The key is the simple concept of "placing two identical texts and moving by -50%." Customizing speed and direction is straightforward, and don't forget to consider accessibility.

Use this technique for news tickers, decorative text displays, and various other applications.