When a viewpoint (a camera or an observer) moves vertically or horizontally while facing the same direction, the elements in the view-field move according to their proximity. Closer objects move faster and more distant objects move slower. This is the parallax effect.
For a better understanding, simply imaging looking through a side window on a car ride. The elements, that are closer to the car (such as guard railing or trees), move relatively much faster than elements, which are farther away (such as distant mountains or the moon).
Such parallax effect can be applied to certain elements of a webpage. When scrolling downwards on a website, some elements can be made to move slower than others, creating a perception of depth (on the z axis) to the website. Some elements cam thus be made to appear closer or farther than the main elements. This works also for horizontal side scrolling, but I am not a fan of that, so I am not going to address that possibility - nonetheless, all features also apply there.
¶ Jump into it quickly - with a library
Forget reading the whole article, I just want an out-of-the-box solution. Now.
A good tool that streamlines this process can be found in this Parallax.js library. This is not the sole library, as there are others as well, like the Paroller.js library. Check them out.
I will be describing three different types of parallax that can be implemented on websites. Each comes with their specific features and implementation tricks. I suggest reading about all of them before selecting the best method to implement on your website.
Images are normally inserted into website HTML code with <img>
tag. But this is not the only way to include images. It is also possible to include images as backgrounds to any element in CSS code. If the element itself is empty, this way has pretty much the same effect as inclusion with <img>
tag.
The image is set as background and fixed onto the viewport, so the scrolling function does not have anny effect on the image and consequently, the image appears to be far behind the other parts of the website.
This is well explained in the w3schools page:
.parallax {
/* The image used */
background-image: url("img_parallax.jpg");
/* Set a specific height */
min-height: 500px;
/* Create the parallax scrolling effect */
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
The only real downside with this approach is that it only allows images to be parallax-ed, and not any other web elements (such as SVG or canvas drawings), due to the limitation of the background-image
property.
There is another way to implement parallax scrolling, discovered and well-described by Keith Clark in the following two articles:
The idea is to introduce two types of elements. First is the wrapper element, which spans across the screen and in which the parallax-layer elements are nested. The wrapper should be the only element in the body and stretch across the whole viewport (height: 100vh
and width: 100%
) on the page. Second are the parallax layers, which are inserted in the wrapper and move across it as the user scrolls (enabled by overflow-y: auto
). The layers are rendered off the screen and rendered in relative to the fixed perspective of the wrapper when the user scrolls far enough.
.parallax-wrapper {
perspective: 1px;
perspective-origin-x: 100%;
height: 100vh;
width: 100%;
overflow-x: hidden;
overflow-y: auto;
scroll-behavior: smooth;
}
.parallax-layer,
.parallax-layer-base,
.parallax-layer-back,
.parallax-layer-front {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform-origin-x: 100%;
padding: 100vh 0;
}
.parallax-layer-base {
transform: translateZ(0);
}
.parallax-layer-back {
z-index: -1;
transform: translateZ(-1px);
}
.parallax-layer-front {
z-index: 1;
transform: translateZ(1px);
}
See the demo of the Keith Clark's parallax implementation here.
My biggest concern is that the whole website needs to be created with paralax design in mind. This design cannot simply be added to an existing website. If the parallax-wrapper element is not the only element in the body, this system will create nested scrolling section, which also means nested scroll bars and bad user experience. For example, if only a single small section of the website is meant to be parallaxed, the whole website still needs to be set with parallax in mind and all other non-parallax elements need to be added as base layers, otherwise this system will create a separate section with parallaxed layers inside and its own scroll-bar. Additionally, the website (<body>
) height is limited to the viewport height as all elements are rendered with no height outside of the screen and not lower on the page, as HTML is meant to be used. This can have some negative effects on other custom elements on your site, so think it through before using.
JavaScript functions can be made to simulate the parallax effect by moving elements according to user's scroll. Whenever the user scrolls the page, a scroll event is fired and if you listen to this event, you can move the parallaxed elements a little bit downwards/upwards, according to the amount scrolled down/up. From the user's perspective, this makes it look like the element moved less than the rest of the page and therefore is perceptually farther away.
let parallaxElements = document.getElementsByClassName('parallax-back');
window.addEventListener('scroll', function() {
var value = window.scrollY;
for (parallaxElement of parallaxElements) {
parallaxElement.style.top = value * 0.33 + 'px';
}
});
This approach allows you to add some other changes to the parallaxed elements as well, such as growing or shrinking them, or moving them sideways - this is not parallax behaviour anymore, but can make your website look interesting.
E.g.
parallaxElement.style.top = value * 0.33 + 'px';
parallaxElement.style.right = value * 0.15 + 'px';
My main concern with this approach is that it uses JavaScript instead of CSS. According to Separation of Concerns principle, the CSS is responsible for styling and visual designs, while JS is for interactivity, responsiveness and animation. In my opinion, the parallax feature is visual design and thus in the domain of CSS. So, using JS instead breaks this principle. Nonetheless, the CSS does not seem to be sufficient for my needs, so JS is, in my oppinion, the way to go.