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

Step-by-step guide on eliminating the modal post-validation

Newbie in reactjs looking for help with modal validation issue. Goal: Press submit button inside modal, validate, then close the modal. Want to reuse modal for another row. Problem: I'm having trouble making the function work for a new row after ...

Can we activate or attach a jQuery UI event?

Similar Question: jQuery AutoComplete Trigger Change Event After successfully implementing the jQuery UI Autocomplete widget using version 1.9, I am curious to know if it is possible to trigger or bind a jQuery UI event. For example, can the jQuery UI ...

Is there a way for me to come back after all child http requests have finished within a parent http request?

I am currently utilizing an API that provides detailed information on kills in a game. The initial endpoint returns an ID for the kill event, followed by a second endpoint to retrieve the names of both the killer and the killed player. Due to the structur ...

What is the best way to access form data in React using a React.FormEvent<HTMLFormElement>?

I am looking for a way to retrieve the values entered in a <form> element when a user submits the form. I want to avoid using an onChange listener and storing the values in the state. Is there a different approach I can take? login.tsx ... interfa ...

Issues have been reported with the functionality of the backbone.js app when switching views, particularly regarding the inconsistent

I am in need of assistance with backbone.js. Whenever a 403 or 401 error occurs, I want to display the login view. Currently, I have attempted the following approach: $(document).on('ready', function(){ app.loadTemplates(['ShellView&apo ...

Eliminating padding or margin for figures in Bootstrap on smaller screens

I've been struggling to create a fullscreen image on small devices without any margin or padding. Unfortunately, the solutions suggested in this thread didn't work for me. Below is the code I'm currently using (tested on https://jsfiddle.n ...

What is the best way to access nested JSON array data that includes varying key names and content?

In my current project, I am trying to extract data from a JSON array. Here is my approach: Below is the jQuery/JavaScript code I used to generate and retrieve data, particularly focusing on the nodes object which determines different layouts: var getPost ...

The page does not seem to be reloading properly due to a redirect issue

I am currently updating some data and then attempting to reload the current page. After discovering the status code that allows me to switch the redirect method from put to get (303), I noticed that it is functioning correctly. However, despite seeing "fi ...

TypeAhead.js and Bloodhound displaying an uneven quantity of search outcomes

I have a frontend setup with TypeAhead and Bloodhound integration, fetching JSON data from a Play/Scala server. The version of Typeahead being used is 0.11.1. Here is how the implementation looks: HTML: <div id="typeahead" class="col-md-8"> < ...

Is there a way to customize jqwidgets jQuery grid cell classes/styles based on row ID and column name?

{ text: 'sell', datafield: 'Sales', width: '3%', columntype: 'button', filterable: false, cellsrenderer: function(row, columnfield, value, defaulthtml, columnproperties) { return &apos ...

Using JQuery to swap out background images in CSS

I have been working on a slider that is supposed to fade one picture over another. The issue is that the background change seems to only work in the Dreamweaver preview and not in the actual browser. loop = setInterval(function(){ $("#slider").css("ba ...

Tips for keeping a specific key value pair as the final entry in a Typescript Object

My goal is to construct a Typescript Object that has a specific element with the key 'NONE' always positioned at the end. This arrangement is crucial for displaying the object in my HTML page with this value appearing last. I am seeking an implem ...

Using JavaScript to create a JSON object within a table

Currently, I am facing a challenge in creating a JSON object from an HTML table using JavaScript. While I can successfully retrieve the values of each cell in JavaScript, the issue lies in organizing and retrieving them as per my requirements. Here is the ...

Incorporate SVG files into a TypeScript React application using Webpack

I am trying to incorporate an SVG image into a small React application built with TypeScript and bundled using Webpack. However, I am encountering an issue where the image is not displaying properly (only showing the browser's default image for when n ...

Error message displayed in Wordpress: "An uncaught SyntaxError was encountered, with an unexpected token &

I have added scripts to a child theme using the following code... function child_theme_scripts() { wp_enqueue_script( 'script-name', get_template_directory_uri() . '/js/custom-child.js', array(), '1.0.0&a ...

Having trouble serving static files with express.Router?

With my file system becoming more complex, I decided to switch from using app.use(express.static()) to utilizing express.Router(). Initially, I thought I could just replace app.use(express.static()) with router.use(express.static()), but unfortunately, thi ...

Grabbing a section of a URL through a bookmarklet: A simple guide

Recently, I've been using this handy bookmarklet: javascript:currentUrl=document.location.href;document.location.assign(currentUrl+'embed'); This neat tool grabs the current URL, such as www.example.com/knZg_INW8fL/, and adds embed to it f ...

Ways to automatically check a checkbox using jQuery

Is there a way to use jQuery to programmatically click a checkbox? I am trying to create a hidden checkbox that will be checked when a user clicks on a specific element, but my current code is not functioning as expected and I am unsure why. You can view ...

Calculate the total of the temporary information entered into the input field

I'm totally new to all of this and definitely not an expert, but there's something that really bothers me. I found a website where you have to complete a captcha to log in. It goes like this: <input type="text" class="form-contr ...

Connecting multiple knockout ViewModels with a single View

I have created multiple knockout ViewModels and now I am attempting to bind them to a single ViewModel, but it is not functioning correctly! The desired behavior is for it to function like a navigation. Once the LoginModel is completed, it should transiti ...