Creating scroll snapping blocks with GSAP v3 animations
In this article we learn to implement scroll-snap with CSS and add animation with GSAP
Setting up some HTML
So firstly I want to say something about using a lot of div
elements.
Stop doing that.
Always try to correctly use semantic elements introduced in HTML5.
1<main>2 <article>3 <h2>So...</h2>4 <h3>This is a story all about how</h3>5 </article>6 <article>7 <h2>The web got flipped, turned upside down</h2>8 </article>9 <article>10 <h2>And i'd like to take a minute and sit right there</h2>11 </article>12 <article>13 <h2>Read my blog, kthnxbye</h2>14 <h3><a href="https://webanimation.blog">webanimation.blog</a></h3>15 </article>16</main>
Adding some CSS
To enable the CSS property scroll-snap
we need to limit the height of the container to a certain value, in this case: 100vh
.
Afterwards we add overflow-y: auto;
to allow scrolling in the container.
Pro tip: Prefer "auto" as the overflow value over "scroll" to remove unwanted scrollbars on Linux machines.
The article
element are the blocks we want to browser to snap to. We add scroll-snap-align: start;
to enable snapping to the top of the container.
All the other code is pretty much just making things look better.
1main {2 scroll-snap-type: y mandatory;3 position: relative;4 max-height: 100vh;5 overflow-y: auto;6}78article {9 height: 100vh;10 width: 100vw;1112 display: flex;13 flex-flow: column nowrap;14 justify-content: center;15 align-items: center;1617 scroll-snap-align: start;18}1920article:nth-of-type(1) {21 background-color: rgba(0, 82, 178, 1);22}23article:nth-of-type(2) {24 background-color: rgba(255, 164, 0, 1);25}26article:nth-of-type(3) {27 background-color: rgba(144, 195, 255, 1);28}29article:nth-of-type(4) {30 background-color: rgba(255, 173, 25, 1);31}3233h2,34h3,35a {36 font: 400 3rem/1.5 sans-serif;37 color: white;38 transform-origin: center;39 text-decoration: none;40}4142h3 {43 font: 400 2em/1.5 sans-serif;44}
Intersection Observer
The Intersection Observer allows you to, no shit, observe intersections.
1// Elements you want to track2const blocks = document.querySelectorAll('main article');34const blocksObserver = new IntersectionObserver(5 entries => {6 // entries === elements7 return entries.forEach(event => {8 // destructures the values we want to check for in the animateVisible function9 const { target, intersectionRatio, isIntersecting } = event;10 // Call function when an intersection triggers.11 animateVisible(target, intersectionRatio, isIntersecting);12 });13 },14 // threshold means the percentage between 0-1 (0 = 0, 1 = 100) when we want the intersection callback to trigger.15 // This Intersection Observer triggers when the element is in view for at least half of it's height.16 { threshold: 0.5 }17);1819for (const block of blocks) {20 blocksObserver.observe(block);21}
Animating in view with GSAP
1// Set all children of the article to invisible (autoAlpha is a mix between CSS properties: opacity and visibility) and downward for 1rem2// Note: * should be avoided because it can cause performance issues, but for this example it was fine.3gsap.set('main article *', { autoAlpha: 0, y: '1rem' });45// Is triggered in the Intersection Bbserver6const animateVisible = (block, ratio, isIntersecting) => {7 // When the element is in view:8 if (ratio > 0 && isIntersecting) {9 // Animate all the children of this element10 gsap.to(block.querySelectorAll('*'), {11 // duration is one second12 duration: 1,13 // animate back to visible14 autoAlpha: 1,15 // animate back to top16 y: '0',17 // stagger will make all animations fire 0.3 seconds after each other.18 stagger: 0.3,19 // Ease In Out: accelerates --> decelerates20 ease: 'power3.inOut',21 });22 } else {23 // When the element is not in view anymore we set it to invisible and downward for 1rem (16px usually)24 gsap.set(block.querySelectorAll('*'), {25 autoAlpha: 0,26 y: '1rem',27 });28 }29};
Final demo
Thanks for reading!
I hope someone somewhere learned something via this post! If you did, please consider sharing the article.
Other posts you might like
Wavy Text Animation using React Hooks with GSAP v3
July 12, 2020In this article i'll create a wavy text animation with React Hooks and GSAP v3 . For the example…
How to: Dual range slider in React with Framer Motion
July 05, 2020In this article I'll show how we achieved to create a dual range slider from scratch in React with…
How I built the Level30Wizards page transition with Gatsby and Framer Motion
July 02, 2020Tech stack The Level30Wizards website is built with: Gatsby for templating, routing, etc. Framer…