For a period in the years 2010, parallax Was a guaranteed way to make your website “cool”. Chris Coyier did indeed write about it in 2008.
For those who are not familiar with the concept, Parallax is a pattern in which different elements of a web page move at different speeds while the user scrolls, creating a three -dimensional, laminated appearance. A real parallax effect was once only feasible with the help of Javascript. However, Scroll-driven animations have now given us a CSS all-solution that is free from the headscarf block that can bully JavaScript animations.
Parallax may have become a small cliché, but I think it is worthwhile to visit this new CSS function again.
Remark: Scroll-driven animations are available on Chrome, Edge, Opera and Firefox (behind a play flag) at the time of writing. Use a supported browser in following this tutorial.
Start code
In this example we will apply parallax animations to the background and icons within the three “Hero” sections of a webpage with a universe theme. We start with a slightly stylized Markup with varied hero and text sections, while we record some space-related nonsense as temporary content.
Add first animations
Let’s add an animation to the background pattern within each hero section to change the background position.
@keyframes parallax {
from {
background-position: bottom 0px center;
}
to {
background-position: bottom -400px center;
}
}
section.hero {
/* previous code */
+ animation: parallax 3s linear;
}Here we use the keyframes CSS rule to make a start and end position for the background. Then we adhere to this animation to each of our hero sections using the animation property.
By default, CSS animations are based on duration and are executed when the specified selector is loaded into the Dom. If you renew your browser, you will see the animation running for three seconds as soon as the page loads.
We do not want our animation to be activated immediately. Instead, we intend to use the scroll position of the page as a reference to calculate the progress of the animation.
Scroll-driven animations offer two new ones time line CSS functions. These additions, view() And scroll()Tell the browser to which refer to the calculation of the progress of a CSS animation. We’ll be the view() Function later, but let’s concentrate on now scroll(). The Scroll -Forward Time Line links the progress from an animation to the scroll position of the user within a scroll container. Parameters can be recorded to change the Scroll axis and the container element, but these are not necessary for our implementation.
Let’s use a Scroll -Purpose Tijdlijn for our animation:
section.hero {
/* previous code */
- animation: parallax 3s linear;
+ animation: parallax linear;
+ animation-timeline: scroll();
}If you renew the page, you will notice that while scrolling down, the position of the background of each hero section also changes. If you scroll again, the animation turns over. As a bonus, this CSS animation is handled from the main thread and is therefore not subject to blocking by a JavaScript that may be active.
Using the display of display
Now let’s add a new parallax layer by animating the header and icons in every hero section. In this way, the background patterns, headers and main page -contents all seem to scroll at different speeds. We will initially the scroll() CSS function here also for the animation time line.
@keyframes float {
from {
top: 25%;
}
to {
top: 50%;
}
}
.hero-content {
/* previous code */
+ position: absolute;
+ top: 25%;
+ animation: float linear;
+ animation-timeline: scroll();
}That’s not quite right. The animation for the sections further down the page is almost done by the time they come into the picture. Fortunately, the display of the display -animation solves this problem. By setting it animation-timeline property view()Our animation is progressing based on the position of the subject in the scrollport, which is part of the container that is visible during scrolling. Just like the timeline of the Scroll animation, the opposite scrolling will also reverse the animation.
Let’s try to change our animation time line for the hero text:
.hero-content {
/* previous code */
- animation-timeline: scroll();
+ animation-timeline: view();
}That looks pretty good, but there is a problem with the header content that flashes in the display when the document scrolls again. This is because the display time line is calculated on the basis of the original, pre-animation positioning of the underwarpelement.
We can solve this by one inset parameter for the view() function. This adjusts the size of the container in which the animation will take place. According to MDN’s documentationThe “deployment is used to determine whether the element is in the eye that determines the length of the animation time line. In other words, the animation takes as long as the element is in the set view.”
So by using a negative value, we make the container larger than the window and activate the animation to start a little and end up a bit after the subject is visible. This explains the fact that the subject moves during the animation.
- animation-timeline: view();
+ animation-timeline: view(-100px);Now, both the text and the background flexibly at different speeds.
Adjust animations with the help of animation straps
So far we have both employed role And reproduction Progress time lines. Let’s look at a different way to adjust the start and end timing of the animations using the animation-range property. It can be used to change where the animation starts and ends along the timeline.
We start by adding a view() Timeline animation to the #spaceship Emoji:
@keyframes launch {
from {
transform: translate(-100px, 200px);
}
to {
transform: translate(100px, -100px);
}
}
#spaceship {
animation: launch;
animation-timeline: view();
}Again, we see the emoji returning to being 0% Position as soon as the original Unanimated position is outside the scrollport.
As discussed earlier, animations are based on the original pre-animation position of the subject. We have previously solved this by adding a bet parameter to the view() function. We can also adjust the animation range and tell our animation to go beyond 100% of the animation time line without having to manipulate the deployment of the reflection line itself.
#spaceship {
animation: launch;
animation-timeline: view();
+ animation-range: 0% 120%;
}Now the animation continues until we have written an extra 20% beyond the normal end point of the calculated Scroll -Tijdlijn.
Let’s say we want to add an animation to the #comet emoji, but we don’t want it to start to animate until it has passed 4rem From the bottom of the scrollport:
@keyframes rotate {
from {
transform: rotate(0deg) translateX(100px);
}
to {
transform: rotate(-70deg) translateX(0px);
}
}
#comet {
animation: rotate linear;
transform-origin: center 125px;
animation-timeline: view();
animation-range: 4rem 120%;
}Here we see the “delayed” animation in action:
We can also combine animation racks to perform completely different animations on different points within the same timeline! Let’s illustrate this by combining animation racks for the #satellite icon at the top of the page. The result is that the first animation runs until the icon passes 80% of the scrollport, after which the second animation takes over for the last 20%.
@keyframes orbit-in {
0% {
transform: rotate(200deg);
}
100% {
transform: rotate(0deg);
}
}
@keyframes orbit-out {
0% {
transform: translate(0px, 0px);
}
100% {
transform: translate(-50px, -15px);
}
}
#satellite {
animation: orbit-in linear, orbit-out ease;
animation-timeline: view();
animation-range: 0% 80%, 80% 110%;
}Fallbacks and Accessibility
Our webpage offers countless moving elements that can cause discomfort for some users. Let us look at the accessibility for sensitive movement and the prefers-reduced-motion CSS Media function.
There are two possible values: no-preferenceAnd reduce. If we want to coordinate the webpage as standard with animations disabled and then want to improve any selector with animations and associated styles, we can use it no-preference To call in them.
@media (prefers-reduced-motion: no-preference) {
.my-selector {
position: relative;
top: 25%;
animation: cool-animation linear;
animation-timeline: scroll();
}
}For us, however, the web page -content and images will still be all visible if we disable all animations at the same time. This can be briefly done with the help of the reduce option. It is important to note that this type of general approach works for our situation, but you must always take into account the impact on your specific users when implementing accessibility functions.
@media (prefers-reduced-motion: reduce) {
.my-selector {
animation: none !important;
}
}In addition to considering accessibility, we must also bear in mind that all browsers are not supported by scroll-driven animations at the time of writing. If we give a lot to users who see our animations, we can add a polyfill (direct link) To expand this functionality to currently non -supported browsers. However, this will force the animation to run on the main thread.
As an alternative, we can decide that performance is important enough to skip the animations about non -supported browsers, making the main thread clear. In this case we can @supports Choice and only add the styles to supported browsers.
Here is the last code with everything, including the polyfill and reduced motionfallback:
Conclusion
There we are going, we have just created a classic web effect with scroll-driven animations with the help of role And reproduction Progress time lines. We have also discussed some of the parameters that can be used to adjust animation behavior. Whether or not Parallax is your thing, I think we can use a modern approach that is able to do what we could do earlier … Only better with a touch of progressive improvement.
More information
#Bring #parallax #scrolldriven #CSS #animations #CSS #tricks

