I created my first scroll-driven animation in CSS
Posted 15 hours ago
I created my first scroll-driven animation using the CSS animation API this week! And it was so easy to create.
Last month, I started watching Bramus’ course on scroll-driven animation, Unleash the power of Scroll Animations. I applied what I was learning by revisiting some scroll-driven animation Codepens that I created with GreenSock (GSAP) (Codepen Collection). I had originally created these prototypes to get some practice because I not build out a project with scroll-driven animations before. I have only built site with scroll-triggered animations in the past.
Recently, I had flirted with the idea of using scroll-driven animations with a project at work. I thought the nature of scroll-driven animations lent itself well to the story-driven nature of the project (an annual report). And I thought it would give me a great opportunity to develop my skills by building out a real project (Just Build Websites). But after some further evaluation, I decided not pursue the scroll-driven narrative.
One of the pieces of this project was a timeline about different ministry projects that are part of a five year initiative. The timeline was one of the last things I built and I decided to go with a horizontal scroll to view the timeline elements. But one of the constraints that I butt up against was that macOS does not show horizontal scrollbars until you start scrolling (I could not find a way to force it with CSS). So there is not an affordance that indicated to the user that they could scroll the element to see more content. I had added a generated content element to fade the content on the right but it still did not seem to give a good affordance.
So I decided to try a scroll-driven animation as a progressive enhancement. It just so happened that the next lesson in Bramus’ course addressed this use case. I watched the video and then studied the demo he created for the lesson.
I only had to add one more element to my markup than I originally had written. I already had a containing div with a unordered list (ul) inside of it. I just had to add a “pin wrapper” div around the unordered list.
<div class="wow-timeline">
<div class="pin-wrap-sticky">
<ul class="pin-wrap">
...
</ul>
</div>
</div>
Because this solution is a progressive enhancement, I put my code for the scroll-driven timeline solution inside a feature query (@supports). The .wow-timeline gets a height of 500vh because it is the scroll of this element that determines the timing of the animation. A higher value would mean a slower scroll animation and lower value, a faster one. I set up a view-timeline by adding a view-timeline-name. A view timeline name is always preceded by two hyphens (like a CSS custom property).
@supports (animation-timeline:scroll()) {
.wow-timeline {
display: flex;
height: 500vh;
overflow: visible;
view-timeline-name: --section-pin-timeline;
view-timeline-axis: block;
}
}
Next you add add CSS for the pin-wrapper. It will be a sticky element so that it looks like your animation is “pinned” to the viewport. I made it a flex element so that I could vertically center my timeline in the viewport. The height is 88px less than 100% to account for a fixed navigation element at the top of the page.
@supports (animation-timeline:scroll()) {
.wow-timeline .pin-wrap-sticky {
display: flex;
align-items: center;
height: calc(100vh - 88px);
position: sticky;
top: 120px;
width: 100vw;
overflow-x: hidden;
}
}
And finally I added CSS to my unordered list. The example from Bramus’ course had a set width. The unordered list is using CSS grid and by setting fit-content, the scroll-driven animation will work across responsive viewports.
@supports (animation-timeline:scroll()) {
.wow-timeline .pin-wrap {
padding-block-end: 0;
width: fit-content;
will-change: transform;
animation: linear forwards move;
animation-timeline: --section-pin-timeline;
animation-range: contain 0% contain 100%;
}
}
@keyframes move {
100% {
transform: translateX(calc(-100% + 100vw));
}
}
Very simple to do. In less than 10 minutes, I had a scroll-driven animation that I progressively enhanced the page with. I highly suggest watching Bramus’s course. It will give you the basics you need to start creating your own scroll-driven animations.
Progressively enhanced scroll-driven timeline:
Default horizontal scroll solution:
Comment on this post