← Back to knowledge base |
  • Web development

Simple scroll parallax

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)';
            }
        }
    });
})();

Check Codepen for a working example

About the author

Milan Lund is a Freelance Web Developer with Kentico Expertise. He specializes in building and maintaining websites in Xperience by Kentico. Milan writes articles based on his project experiences to assist both his future self and other developers.

Find out more
Milan Lund