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.
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.
<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>
@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.
<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>
@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.