parallax scrolling can be a bit bumpy

While working on a website, I've incorporated a slight parallax effect that is functioning almost perfectly. However, I've noticed that the foreground divs tend to jump a little when scrolling down the page.

At the top of the page, there is a div called #top-banner with a fixed background image. Inside this div, there are two more divs placed in a row. The first div/column contains an image of a model, while the second div has text content.

Directly below the #top-banner div is another div with a background image depicting a waterline. The objective is to make it appear as if the waterline is covering the #top-banner as users scroll down, giving the illusion that the model, text, and background are submerged under water.

To achieve this effect, I used jQuery to adjust the CSS properties dynamically. By changing the bottom property of the columns divs, they appear to move downwards beneath the waterline at a speed relative to the user's scrolling motion. Small variations in speeds create the desired parallax effect.

Although the implementation works reasonably well, there are noticeable jitters. I attempted to use jQuery's animate function as well, but the result was even jerkier.

HTML

<section id="top-banner">
    <div class="row">
        <div class="col-2 prlx-1">
            <img src="model.png"/>
        </div>
        <div class="r-col-2 prlx-2">
            <h3>Lorem Ipsum</h1> 
            <p>More Ipsum</p>
        </div>                            
</section>   

<section id="hp-water-line"></section>

CSS

#hp-top-banner {
  background: url(bg.png);
  height: 600px;
  background-attachment: fixed;
  background-origin: initial;
  background-clip: initial;
  background-size: cover;
  overflow: hidden;
  width: 100%;
  position: relative;
}

#hp-water-line {
  background: url(water-line.png) no-repeat transparent;
  min-height: 92px;
  margin: 0 auto;
  width: 100%;
  position: relative;
  top: -15px;
  background-size: cover;
}

JS

$(document).ready(function(){

    function parallax(){
        var prlx_effect_1= -((window.pageYOffset / 4) *2.25 );
        $('.prlx-1').css({"position": "relative","bottom":prlx_effect_1, "transition": "0s ease-in-out"});
           // jQ('.prlx-1').css({"position": "relative"});
           // jQ('.prlx-1').animate({"bottom":prlx_effect_1},"fast");

        var prlx_effect_2= -(window.pageYOffset / 5 );
        $('.prlx-2').css({"position": "relative","bottom":prlx_effect_2, "transition": "0s ease-in-out"});

    }

    window.addEventListener("scroll", parallax, false);

});

Updated JS based on Prinzhorn Comment

var requestAnimationFrame = window.requestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    window.oRequestAnimationFrame;

function onScroll() {
    requestAnimationFrame(parallax);
}

function parallax(){
    var prlx_effect_1= +(window.pageYOffset *.7).toFixed(2); // .55 is a good speed but slow
    var prlx_str_1 = "translate3d(0, "+prlx_effect_1+"px, 0)";
    jQ('.prlx-1').css({
        "transform":prlx_str_1,
        "-ms-transform":prlx_str_1,
        "-webkit-transform":prlx_str_1
    });

    var prlx_effect_2= +(window.pageYOffset * 1 ).toFixed(2); // .33 is a good speed but slow
    var prlx_str_2 = "translate3d(0, "+prlx_effect_2+"px, 0)";
    jQ('.prlx-2').css({
        "transform":prlx_str_2,
        "-ms-transform":prlx_str_2,
        "-webkit-transform":prlx_str_2
    });

    requestAnimationFrame(parallax);

}

window.addEventListener("scroll", onScroll, false);

Answer №1

Before, I used to construct parallax websites by manipulating background-position or margins with jquery. However, my perspective shifted after reading an insightful article a few months ago.

The author recommended utilizing CSS properties like translateZ and perspective to bring containers or images forward and backward in a 3D space for a more authentic parallax effect. This approach not only results in smoother animations but also enhances the performance on mobile devices. Personally, I find this method much simpler to implement.

For example:

.parallax {
    perspective: 1px;
    height: 100vh;
    overflow-x: hidden;
    overflow-y: auto;
}
.parallax__layer {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
}
.parallax__layer--base {
    transform: translateZ(0);
}
.parallax__layer--back {
    transform: translateZ(-1px);
}

One challenge of using genuine 3D layers is being strategic with your Z-Index to prevent unintended layer overlaps.

The mentioned article includes a fantastic demo where you can visualize the side profile of the 3D space and observe how the layers are arranged along the z-axis. Simply click the 'debug' button in the top-left corner.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to dynamically assign width to elements in a v-for loop in Vue.JS

I am working with HTML code that looks like this: <div v-for="(s, k) in statistics" v-bind:key="s.id" class="single-stat"> <div class="stats"> { ...

Tips on resolving the Hydration error in localStorage while using Next.js

Having issues persisting context using localStorage in a Next.js project, resulting in hydration error upon page refresh. Any ideas on how to resolve this issue? type AppState = { name: string; salary: number; info: { email: string; departme ...

The header and navigation bar are both set to stay in place, but unfortunately my div element is not displaying beneath

After setting both the Nav and Header to fixed, everything seems to start out well. I adjust the Nav margin-top so that it appears below the header, which works fine. However, things take a wrong turn when I try adjusting the div. The div ends up behind th ...

Table lines that are indented

I am currently in the process of transforming a standard HTML table into an indented version like this: Is there a way to hide the initial part of the border so that it aligns with the start of the text, even if I can't do it directly in HTML? ...

Determine the hour difference between two provided dates by utilizing the date-fns library

My API returns a "datePublished" timestamp like this: "2019-11-14T14:54:00.0000000Z". I am attempting to calculate the difference in hours between this timestamp and the current time using date.now() or new Date(). I am utilizing the date-fns v2 library fo ...

The app is having trouble loading in Node because it is unable to recognize jQuery

I am currently using Node to debug a JavaScript file that includes some JQuery. However, when I load the files, the $ sign is not recognized. I have installed JQuery locally using the command npm install jquery -save-dev. The result of "npm jquery -versio ...

Is there a way to prevent users from copying data or switching tasks when using my program or website?

Is it feasible to develop a website or application for Windows desktop machines that can remain focused until the user completes a specific task? For instance, if my YYY app/website is open and I require the user to input some text, I want to restrict the ...

What is the best way to interact with an element in Python Selenium once it has been located?

I have been working on a script that is supposed to retrieve the attribute of an element and then click on it if the value is true. However, I keep encountering an error in my code. This is the snippet of code I am using: from selenium import webdriver d ...

Can someone please explain how to prevent Prettier from automatically inserting a new line at the end of my JavaScript file in VS Code?

After installing Prettier and configuring it to format on save, I encountered an issue while running Firebase deploy: 172:6 error Newline not allowed at end of file eol-last I noticed that Prettier is adding a new line at the end when formatting ...

Is there a way to incorporate two Bootstrap navbars on a single page that are of varying heights?

Utilizing Bootstrap 3.0 with dual navbars on a single page that adjust in height using the same variable for both .navbar blocks. Despite attempting to incorporate an additional class to alter the height of the initial navbar, it remains unaffected. Check ...

What are some ways to expand the width of a MaterialUI form control if no value has been chosen?

I am currently working on a project where I need a dropdown menu component with specific selections. However, the layout appears to be cramped and I'm struggling to adjust the width. Additionally, I've been unsuccessful in changing the font size ...

Can a single SVG file be referenced and reused multiple times in a project?

Instead of repeating these code blocks: <svg class="icon-user"> <use href="LONGFILENAME.svg#icon-user"> </use> </svg> <svg class="icon-user2"> <use href="LONGFILENAME.svg#icon-user2"> </use> </ ...

A cutting-edge JQuery UI slider brought to life using HTML5's data-* attributes and CSS class styling

I've been attempting to create multiple sliders using a shared CSS class and HTML5 data attributes, but unfortunately, I haven't had much success so far. Although I am able to retrieve some values, there are certain ones that simply aren't w ...

The information sent via POST (via fetch JavaScript with PHP8) is not being received by PHP8

My PHP8 server is not receiving the data I am sending. When trying to insert a new song into my API, an error occurs and in the console, I see an object with POST as an empty array. fetch("http://localhost/api.audio-player/",{ method: 'POST&apos ...

Tips for modifying jsFiddle code to function properly in a web browser

While similar questions have been asked before, I am still unable to find a solution to my specific issue. I have a functional code in jsFiddle that creates a table and allows you to select a row to color it red. Everything works perfectly fine in jsFiddle ...

What could be causing my border to spill over into the adjacent div?

Trying to set up the contact section of my portfolio but running into an issue where the border of one div is overflowing into the next. Here's a snippet of the code: //CSS .contact-cont { padding: 4rem 12rem 0rem; height: 90vh; ...

Using JavaScript to listen for events on all dynamically created li elements

Recently, I've created a simple script that dynamically adds "li" elements to a "ul" and assigns them a specific class. However, I now want to modify the class of an "li" item when a click event occurs. Here's the HTML structure: <form class ...

Bootstrap Dropdown Functionality Malfunctioning

Here is a simple piece of HTML code that I have created: <!doctype html> <html> <head> <meta charset="utf-8"> <title>.:Home Page:. The Indian Sentinel</title> <link rel="stylesheet" href=" ...

Implementing AJAX functionality in Codeigniter modulesTo integrate AJAX capabilities within Codeigniter modules

I am currently working on a webpage using the CodeIgniter framework. I am looking to integrate a 'show more' button that will utilize 'ajax.php' to retrieve data from the database and dynamically display it on the site. I prefer for thi ...

Submit a form using Ajax without having to reload the page

Seeking help for implementing an ajax form submission with four answer options to a question. The goal is to submit the form without reloading the page upon selecting an option. Below is the code I have been working on. Any suggestions or solutions are wel ...