Recently, a designer asked me to add a parallax background image on a website. I researched the web to find a suitable solution. Regrettably, I found only massive libraries that would do the thing but bring in a lot of unnecessary javascript code. That is no go for me. I wanted a lightweight and straightforward solution. It took me a while, but I came up with the following code that works perfectly for my needs and hopefully will serve you well too. Check Codepen for a working example.

The first thing we need is HTML and CSS
- DIV with the data-parallax attribute is a container that holds the parallax image and content
- DIV with the data-parallax-target attribute stands for the parallax image. It is positioned absolutely to the parent element and moves as a user scrolls thanks to javascript code (explained below). The key here is that the data-parallax-target element has the bottom property set to be higher than its parent element.
- DIV with the content class name is positioned relatively and contains everything that we want to render on top of the parallax image.
<div data-parallax="hey">
<div data-parallax-target="hey"></div>
<div class="content">
<h1>Hello world</h1>
</div>
</div>
[data-parallax] {
position: relative;
overflow: hidden;
}
[data-parallax-target] {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: -200px;
background-image: url('https://www.milanlund.com/img/splash/about-me--480.jpg');
background-size: cover;
background-position: center center;
transform: translate3d(0, 0, 0);
transition: transform .1s linear;
}
h1 {
padding: 3em 1em;
}
.content {
position: relative;
}
And of course a bit of javascript code
On the scroll event, the code checks whether the data-parallax element is in the viewport. If positive, the translate position gets computed for the data-parallax-target so that the image moves. For better performance, you can use a passive event listener for the scroll event.
(function () {
var parallax = document.querySelectorAll('[data-parallax]');
window.addEventListener('scroll', function () {
for (var i = 0; i < parallax.length; i++) {
var parallaxTarget = document.querySelector('[data-parallax-target="' + parallax[i].getAttribute('data-parallax') + '"]');
var viewportOffset = parallax[i].getBoundingClientRect();
var visibilityIndex = viewportOffset.top / window.innerHeight * 100;
if (visibilityIndex >= 0 && visibilityIndex <= 100) {
var parallaxOffset = parseInt(getComputedStyle(parallaxTarget).bottom);
parallaxTarget.style.transform = 'translate3d(0, ' + Math.floor(parallaxOffset - (visibilityIndex / 100 * parallaxOffset)) + 'px, 0)';
}
}
});
})();
Further reading
all posts- Kentico Xperience
Social media share urls enhanced by Kentico macros
Requirements of nearly every website ask us to incorporate links for sharing content on social media. There are tools out there which generates these links for us. But wh…
- Kentico Xperience
Sync form submissions with Integration bus in Kentico Xperience
In this post, I will provide you with a code snippet and tips on how to synchronize new form submissions with an external system through its REST API using the Integration bus in K…
- Front-end & JavaScript
Table of contents in Javascript
In this post, I will provide you with a javascript code sample that transforms headings in a page into a structured table of contents with anchor links.