Achieving a continuous 2-layer css parallax background in Firefox using css properties "transform" and "perspective" while ensuring the background remains visible beyond content height

You are my final hope. I made a decision to add an update to the Page of my brother's store. One of the new features I wanted was a simple parallax background with two layers to create a sense of depth while scrolling.

At first, I managed to make it work using a bit of JS, adjusting the position on scroll events with a multiplier. However, I soon realized that the performance of the background was sticky, sluggish, stuttering, and not visually pleasing in Firefox. It seemed to be related to the "Asynchronous Panning" feature of the browser.

Click here for the JS-Version of the page update

After some time searching online, I couldn't find a way to disable or bypass that feature, so I decided to attempt a CSS-only implementation instead.

And wouldn't you know it? Firefox was the browser that couldn't display everything as intended!

Initially, I tried putting all my content into divs with the hope that a common parent div would allow me to use "height: 100%;" to scale the divs together. Unfortunately, this approach didn't work because the background overflowed over my content. The challenge arose from wanting the background images to repeat on the y-axis and move at a slower pace than the content, which required specifying a specific height for the background divs larger than the content height.

I even attempted setting the height of the background divs with jQuery using:

$(#background).height($(.main_content_container).height());

but the background kept turning out either too large or too short.

When my idea with the parent div failed, I turned to working directly with the body and my content container to create perspective. Would setting all heights to 100% have worked? Whenever I set height: 100%;, I always got my viewport's height...

My current approach involves creating perspective and applying transforms with the body causing the overflow-y:

    body {
      overflow-y: auto;
      overflow-x: hidden;
      perspective: 1px;
      width: 100%;
      margin-left: 0px;
      margin-top: 0px;
      position: fixed;
      height: 100vh;
      transform-style: preserve-3d;
      align-items: center;
      align-content: center;
      align-self: center;
      text-align: left;
      width: 100vw;
    }
    #background {
      position: fixed;
      bottom: 0;
      left: 0;
      transform: translateZ(-2px) scale(3);
      width: 100vw;
      background-size: 100vw;
      background-image: url(websiteimage.png);
      left: 0;
      right: 0;
      top: 0;
      height: 500vh;
      min-width: 100vw;
    }
    #background2 {
      position: fixed;
      bottom: 0;
      left: 0;
      transform: translateZ(-3px) scale(4);
      background-image: url(websiteimage2.png);
      background-size: 100vw;
      left: 0;
      right: 0;
      top: 0;
      height: 500vh;
      min-width: 100vw;
      opacity: 80%;
    }
div.main_content_container {
  transform: translateZ(0);
  height: 100%;
  background-color: transparent;
  color: Silver;
  max-width: 100vw;
  width: 70%;
  min-height: 100%;
  }

Live demo (only startpage and only in dark mode is functional at the moment)

Why does Chrome crop the bottom of the background divs correctly, but Firefox creates visible overflow? Is there any chance of getting one of my solutions to work smoothly and properly formatted in Firefox?

I've been struggling with this for days now, and I appreciate any ideas or suggestions.

PS: This is my first post on StackOverflow. I hope I provided enough information and didn't violate any rules since this site has often helped me navigate the world of amateur web design.

PPS: I'm aware that my code is somewhat messy after all the tinkering, but I've been experimenting for days now

Answer №1

For those facing a similar issue:

I experimented with various tweaks in my JavaScript implementation and found an enhancement by including

position: fixed;
background-attachment: fixed;
background-position: top;

within the background layers.

I also incorporated a script by Keith Clark, though I am uncertain of its impact:

/*
Firefox super responsive scroll (c) Keith Clark - MIT Licensed
*/
(function(doc) {
console.log("Document executed")
  var root = doc.documentElement,
      scrollbarWidth, scrollEvent;

  // Not ideal, but better than UA sniffing.
  if ("MozAppearance" in root.style) {

    // determine the vertical scrollbar width
    scrollbarWidth = root.clientWidth;
    root.style.overflow = "scroll";
    scrollbarWidth -= root.clientWidth;
    root.style.overflow = "";

    // create a synthetic scroll event
    scrollEvent = doc.createEvent("UIEvent")
    scrollEvent.initEvent("scroll", true, true);

    // event dispatcher
    function scrollHandler() {
      doc.dispatchEvent(scrollEvent)
    }

    // detect mouse events in the document scrollbar track
    doc.addEventListener("mousedown", function(e) {
      if (e.clientX > root.clientWidth - scrollbarWidth) {
        doc.addEventListener("mousemove", scrollHandler, false);
        doc.addEventListener("mouseup", function() {
          doc.removeEventListener("mouseup", arguments.callee, false);
          doc.removeEventListener("mousemove", scrollHandler, false);
        }, false)
      }
    }, false)

    // override mouse wheel behaviour.
    doc.addEventListener("DOMMouseScroll", function(e) {
      // Don't disable hot key behaviours
      if (!e.ctrlKey && !e.shiftKey) {
        root.scrollTop += e.detail * 16;
        scrollHandler.call(this, e);
        e.preventDefault()
      }
    }, false)

  }
})(document);

No noticeable improvement on iOS Safari and mobile Firefox to my knowledge.

Edit: The jQuery function responsible for this effect is as follows:

$(function() {
  $(window).on('scroll', function() {
    $('#background').css('background-position-y', $(window).scrollTop() * -.15);
  });
});  
$(function() {
  $(window).on('scroll', function() {
    $('#background2').css('background-position-y', $(window).scrollTop() * -.09);
  });
  });

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

Creating a luminous impact on objects in three.js by utilizing OBJ and MTL loaders

I am striving to recreate the luminescent effect seen in the image below on my pants obj: sample image This is the current code I have: //pants map and obj var mtlLoader = new THREE.MTLLoader(); mtlLoader.setBaseUrl( 'Ftest2/' ...

The function applyMiddleware in React Redux is not working correctly

After thoroughly reviewing my code, I couldn't find any flaws, yet I received this error message: Uncaught TypeError: (0 , _reactRedux.applyMiddleware) is not a function import { applyMiddleware, createStore } from 'react-redux' impor ...

Experience seamless slide transitions with the react-slick carousel using scroll events in React JS and JavaScript

Currently utilizing the carousel library found at: react-slick I am interested in enabling mouse scroll functionality to navigate through each slide. The idea is to scroll up to progress forward and scroll down to go backward. Came across a relevant exa ...

Unable to change background image to an external image link

<div class="flipbook-viewport"> <div class="container"> <div class="flipbook"> <div style="background-image:url("https://example.com/images/lareg/1.JPG")">< ...

Creating a sleek and stylish panel with a static horizontal table size in Bootstrap 3.0

I'm having trouble with the nested table staying a static large size while the panel decreases as I resize my browser. Any tips on how to fix this? <div class="panel panel-primary"> <table class="table"> ... Here is an exampl ...

Tips for enhancing a table cell using JavaScript

Is it possible to use javascript to style a specific cell in an HTML table? A sample HTML table is provided below: <table border="1" width="300" height="200"> <tr> <td id="11">& ...

Achieving the ideal 3-column design

I'm currently struggling to achieve a proper 3 column layout with my HTML and CSS code. Here's what I have: <div class="row"> <div class="col">C1</div> <div class="col">C2</div> <div class="col">C3 ...

What is the reason behind only being able to toggle half of the element's classes?

My current project involves using jQuery's .toggleClass() function to implement a favorite button within multiple <div> elements, each containing an <a> element and an <i> element. I am toggling between two Font Awesome icons by swit ...

Error: Unable to find the transport method in Socket.io

I recently implemented user side error logging on my website to track errors. I have noticed that sometimes it logs a specific error related to socket.io code: TypeError: this.transport is undefined This error seems to only occur for users using Firefox ...

What is the best way to dynamically insert columns into HTML code?

This is an example of my HTML code: <div class="row text-center"> <div class="col h4">We Collaborate With:</div> <div class="col">company1</div> <div class="col">company2</div> ...

Error: The Jquery plugin Object #<HTMLDocument> does not have a function called 'observe'

Hello, I recently tried to install the Jquery plugin known as chosen that allows customization of my <select> tag across different browsers. If you're interested, you can find more information about it here. However, after integrating this plugi ...

Comparing AngularJS $http with $http.post: A Detailed Analysis

As a newcomer to AngularJS, I am experimenting with sending data to the server and mapping it to a DTO in a REST Service. Here's how I attempted to do it: saveUserUrl = "http://localhost:8080/App/rest/UserManager/saveUser"; var res ...

The communication between socket.io encountered a net::ERR_SSL_PROTOCOL_ERROR

Here is the client code I am using: const socket = io(url); And this is the server code running on a Linux server with Express: const server = require("http").createServer(app); However, when I attempt to establish a connection, an error occurs. https:/ ...

Error Encountered when Attempting to Change Forms Dynamically in CRM 2011: JavaScript Code Execution Problem

Upon form load, I check the type of the form and dynamically load the appropriate form based on that. It was working fine, but when the form reloads to the new form, I encounter a "JavaScript" error which says "cannot execute code from freed script" in Eng ...

Retrieve all HTML components with LXML

I have a large div element in my HTML document that I need to parse in order to retrieve all of its HTML content as well as any nested tags. Here is the code I am currently using: innerTree = fromstring(str(response.text)) print("The tags within the speci ...

Tips for handling two JSON array objects with JavaScript

This particular function public function groups_priviledges($user_id = NULL){ $data['groups'] = $this->priviledges_model->admin_groups(); $data['member'] = $this->priviledges_model->empAdminGroup($user_id); echo ...

Guide on excluding the <src and <href tags from a JSON response in Blogger

"content": "\u003cvideo controls width=800 autoplay\u003e\n \u003csource src=\"https://srv-file8.gofile.io/download/AEiT5Y/www.4MovieRulz.ch - Sunny Winter (2020) 720p Hindi Part-2 HDRip x264 AAC 500MB.mkv&bs ...

Display Binary Image in HTML Table using Server-side Code

I am currently working on creating a table that will retrieve binary image data from a database and display it in an HTML table. Here is the markup I have used: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml1 ...

Angular version 1.6 with ES6, no errors in the application

Can you help me understand this? Note: I am using ui-router, and I suspect that is the issue. $stateProvider .state('login',{ url:'/', /*controller:'loginController',*/ controller: function(){aler ...

Is there a way to completely clear a form using jQuery in JavaScript?

I have a functioning script that sends emails via Ajax and PHP. However, I am also looking to reset the form after sending an email. Below is my jQuery code: <script src="http://code.jquery.com/jquery-latest.js"></script> <script> $(doc ...