If, like me, you’re looking for ways to add a little movement to your web projects using only CSS, this case study on how I set up an infinite horizontal scroll in one of my web projects might be helpful.
It’s simple and brief, but I hope it’ll be useful to anyone trying to reduce the amount of JS on their website while keeping things cool and animated.
Why traditional CSS instead of shiny JS?
The main point is: I don’t speak JavaScript 🤡
I could argue that this has been an effort to make the website as low-carbon as possible. A firm commitment to my values regarding environmental sustainability and all that.
But.
The truth is that I don’t want my lack of this skill to limit the user experience on the websites I build myself (fortunately, they’re the minority. I love you, developers).
And yes, avoiding JS usually helps reduce the size of your website.
So, summing up, I want things to be as simple and accessible as possible for me, while keeping them relevant in terms of user experience and aligned with my low-carbon approach.
Why an infinite horizontal scroll?
Visualize the situation:
A DJ contacts me to design his website. He wants to showcase his photos, his promo video, his media kit, and his music productions in a professional yet sparkly way.
And I want to keep it as low-carbon as possible while following the brief.
First, coffee.
Then, finding a way to keep things light but shining bright like a diamond.
Pure CSS animations seemed like the best option. And since I’m not a big fan of UI elements constantly appearing and sliding around, a horizontal loop felt like a good way to add some movement and rhythm to the static content.
No deep reasons here either.
What about the code?
The first thing I did was dive into CodePen, where I found this:
https://codepen.io/jamesneufeld/pen/myVZJRq
(thank you, James Neufeld from Vancouver ❤️)
Then, I used a custom HTML block to add both the HTML and CSS code. This is what they look like after adapting the CodePen example:
Click to view the HTML code
<div class="marquee">
<div class="marquee__track">
<!-- Original content block -->
<div class="marquee__content">
<ul class="marquee__list">
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
</ul>
</div>
<!-- One duplicate only -->
<div class="marquee__content">
<ul class="marquee__list">
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
<li class="marquee__item marquee__item--text">
<p>Media Kit</p>
</li>
</ul>
</div>
</div>
</div>
Click to view the CSS code
.text-horizontal-animation {
display: flex;
flex-direction: column;
}
/* The outer container — holds everything in place */
.marquee {
position: relative;
width: 100%;
min-height: 20vh;
overflow: hidden;
display: flex;
align-items: center;
}
/* The moving "track" that slides left to right */
.marquee__track {
display: flex;
flex-shrink: 0;
white-space: nowrap;
animation: marquee-scroll 60s linear infinite;
}
/* Animation: moves the track smoothly across the screen */
@keyframes marquee-scroll {
fomt {
transform: translateX(0);
}
to {
transform: translateX(-50%);
}
}
/* Each block of repeated content (we duplicate it in HTML) */
.marquee__content {
display: inline-flex;
flex-shrink: 0; /* Prevents shrinking */
}
/* The list and items inside the marquee */
.marquee__list {
display: flex;
align-items: center;
margin: 0;
padding: 0;
list-style: none;
}
/* Base style for all items */
.marquee__item {
padding: 0 1.2rem;
display: flex;
align-items: center;
justify-content: center;
}
/* Image-specific item */
.marquee__item--image {
width: 5rem;
}
/* Image formatting */
.marquee__item--image img {
width: 100%;
height: auto;
display: block;
}
/* Text item formatting */
.marquee__item--text p {
font-family: var(--wp--preset--font-family--xband-rough);
font-size: 10rem;
font-weight: 900;
text-transform: uppercase;
background: orange;
-webkit-background-clip: text;
background-clip: text;
color: transparent;
margin: 0;
white-space: nowrap;
opacity: .6;
word-spacing: -24px;
}
You can check out the final result here.
I have a feeling there must be an easier way to do this, but it was my first time doing it, and it works, so that’s good enough for me.
Go, CSS!
JS has been the king of motion in web design for a long time. But CSS has emerged as a great alternative for people who want to keep things as light as possible, and also for those who can’t code in JavaScript.
Of course, you can’t do everything with CSS that JS has to offer. But in many cases, it’s a more sustainable, accessible (in skill terms), and easier-to-maintain alternative.
Let’s talk CSS
I’m quite motivated to learn CSS as a way to create animations without having to use JavaScript. So it’d be very helpful if you shared any improvements, comments, or tips you may have about my solution for the infinite horizontal scroll.
And please, let me know of any examples of cool animations you especially like that look like JS but are actually pure CSS.
Leave a Reply