Fly in animation on scroll with CSS and JavaScript
Let’s make a fly in animation on scroll with css custom properties and the intersection observer.
Here’s a codepen of what we will be making. It’s not really refined and has few issues.
The HTML
Let’s start with the HTML. It’s a basic design with 4 sections. A title in the first section. The second section has a grid of cards that will fly up when the user scrolls. The third section has text on the left and an image that will fly-in from the right. The last section just has some text and no animation.
The CSS
The CSS uses custom properties because I like them. After the block of CSS I’ll highlight some of the decisions I made.
The first thing of interest is the is()
. I’m kind of templating the h1, h2, h3
. As you can see below the is()
I’m scaling the font size of the h tags by multiplying them. Ideally I would prefer to use the :where()
pseudo selector because it has 0 specificity but I needed to override the normalize css that is being used in the codepen.
The next thing to look at in the CSS is the .card-grid
and .card-row
. Both have the same custom properties scoped to themselves. They are the same so the intersection observer can easily change the the values that animate without having to do any conditional statements. Although the values are not applied directly to the image, the image will inherit it because of the cascade. There is also an --translate-init
property whose sole purpose is to make the reset easier. I could of done the same for --transition
and --opacity
but the values are the same for both the .card-grid
and .card-row
classes and they are only switching between 2 values.
The last thing to look at is the @media (prefers-reduced-motion: reduce)
media query. This checks if the user has reduced motion set in their accessibility settings. If they do, the animation will be disabled.
The last thing to do is setup the intersection observer to handle the animations. The code seems straightforward to me. It sets the intersection observer to observe all the elements with .intersection-sentry
class. When it intersects, it sets the custom properties to animate the element and un-sets when it is not intersecting.