The scrolling behavior varies in Firefox when using the mouse wheel

Currently, I am working on a website where I want to display large text on the screen and have the ability to scroll two divs simultaneously. This functionality is already in place. I can scroll the divs, but I'm facing an issue with the jumps being too big on the #back div. The jumps seem to match the window's height (you may need to view the snippet in full-screen mode to fully grasp what I mean).

UPDATE: After testing with a friend, it seems that the problem only occurs in Firefox on Windows. It works fine on Mac and Linux. Here is a fiddle with increased height for reference

I've included two gifs to demonstrate the strange effect. Each page movement equals one scrollwheel down on my mouse (works fine with trackpad as well since it's not related to the mouse wheel). https://i.sstatic.net/bxJap.gif

On the other hand, when I remove one of the overflow in my CSS, the following black square stops functioning properly, but the scrolling returns to normal: https://i.sstatic.net/G4Ait.gif


IMPORTANT EDIT: The issue appears to be specific to Firefox, as it functions correctly in Chrome and Brave browsers. I am actively searching for a solution to make it work seamlessly across all platforms.

I noticed that the problem arises when I set two overflows in the CSS. If I remove one, the script breaks, but the scrolling issue also disappears. Here is an example showcasing the bug:

let back_innerHeight = $("#back").height()
let back_scrollHeight = document.querySelector("#back").scrollHeight
 
let front_innerHeight = $("#front").innerHeight()
let front_scrollHeight = $("#front")[0].scrollHeight

$("#back").on("scroll", function () {
  
  // Get how many pixels were scrolled on #back
  let back_scrolled = $(this).scrollTop()
  
  // Calculate the scrolled percentage
  let percentage_back = back_scrolled / (back_scrollHeight - back_innerHeight)
  
  // Calculate how many pixels to scroll on #front
  let scrollIT = (percentage_back * (front_scrollHeight - front_innerHeight))
  
  // Just to validate that the percentage is applied correctly...
  let percentage_front = scrollIT / (front_scrollHeight - front_innerHeight)
  
  
  // Apply the scroll
  $("#front").scrollTop(scrollIT);
});

window.onresize = function(){
  back_innerHeight = $("#back").height()
  back_scrollHeight = document.querySelector("#back").scrollHeight
  front_innerHeight = $("#front").innerHeight()
  front_scrollHeight = $("#front")[0].scrollHeight
}
.scroll {
  position: absolute;
  display: block;
  top: 0;
  height: 100%;
}
#front {
  overflow: hidden;
  position: absolute;
  background-color: black;
  color: white;
  right: 0;
  left: 0;
  bottom: 0;
  top: 0;
  margin: auto auto auto auto;
  width: 25%;
  height: 35%;
  font-size: 3rem;
}
#back {
  overflow: auto;
  font-size: 8rem;
}

p {
  margin: 0;
  padding: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class ="scroll" id="back">
  <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Autem, quam similique quibusdam libero voluptatum laboriosam, sunt possimus non nobis recusandae, excepturi ex voluptates! Neque veniam, sapiente magnam fuga unde autem.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat consequatur consectetur laudantium voluptatibus, iusto molestiae fugit inventore rerum, sit sed dolor ratione perferendis beatae molestias. Asperiores odio mollitia quisquam voluptates.</p>
</div>

<div class ="scroll" id="front">
  <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Autem, quam similique quibusdam libero voluptatum laboriosam, sunt possimus non nobis recusandae, excepturi ex voluptates! Neque veniam, sapiente magnam fuga unde autem.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat consequatur consectetur laudantium voluptatibus, iusto molestiae fugit inventore rerum, sit sed dolor ratione perferendis beatae molestias. Asperiores odio mollitia quisquam voluptates.</p>
</div>

Answer №1

UPDATE

The following provides guidance on achieving a scroll synchronization effect between two div elements, particularly focusing on Firefox behavior and the calculation of scroll percentages.

Regarding Scroll Synchronization:

The key lies in understanding the mathematical aspects involved and identifying the correct values to utilize.

To accurately calculate the percentage of scrolled content relative to what is scrollable, consider the following three essential values for the #back element:

  • A: The visible portion of the div, determined using .innerHeight()
  • B: The number of scrolled pixels, obtained with .scrollTop()
  • C: The total height of the div, inclusive of both the already scrolled content (above) and the pending scroll region (below). This is represented by the scrollHeight property.

To derive the correct percentage, apply the formula: B/(C-A).

Subsequently, utilize this percentage value to determine the "scrollable pixels" for the #front, which equates to the full height minus the visible height.

With these steps, you should achieve the desired synchronized scroll effect.

let back_innerHeight = $("#back").height()
let back_scrollHeight = document.querySelector("#back").scrollHeight
 
let front_innerHeight = $("#front").innerHeight()
let front_scrollHeight = $("#front")[0].scrollHeight

$("#back").on("scroll", function () {
  
  // Calculate the amount of scrolling on #back
  let back_scrolled = $(this).scrollTop()
  
  // Compute the scrolled percentage
  let percentage_back = back_scrolled / (back_scrollHeight - back_innerHeight)
  
  // Determine the required scroll amount on #front
  let scrollIT = (percentage_back * (front_scrollHeight - front_innerHeight))
  
  // Validate the application of the percentage...
  let percentage_front = scrollIT / (front_scrollHeight - front_innerHeight)
  
  console.log("Scroll % BACK:", percentage_back, "FRONT:", percentage_front)
  
  // Apply the calculated scroll
  $("#front").scrollTop(scrollIT);
});

window.onresize = function(){
  back_innerHeight = $("#back").height()
  back_scrollHeight = document.querySelector("#back").scrollHeight
  front_innerHeight = $("#front").innerHeight()
  front_scrollHeight = $("#front")[0].scrollHeight
}
div {
}
#front {
  overflow: hidden;
  position: fixed;
  background-color: black;
  color: white;
  right: 0;
  left: 0;
  bottom: 0;
  top: 0;
  margin: auto auto auto auto;
  width: 25%;
  height: 35%;
  font-size: 3rem;
}
#back {
  height: 95vh;
  overflow: auto;
  overflow-x: hidden;
  overflow-y: auto;
  font-size: 8rem;
}

p{
  margin:0;
  padding:0;
}

/* For demo purposes only... minimizing SO console */
.as-console-wrapper{
  height: 1.4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="back">
  <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Autem, quam similique quibusdam libero voluptatum laboriosam, sunt possimus non nobis recusandae, excepturi ex voluptates! Neque veniam, sapiente magnam fuga unde autem.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat consequatur consectetur laudantium voluptatibus, iusto molestiae fugit inventore rerum, sit sed dolor ratione perferendis beatae molestias. Asperiores odio mollitia quisquam voluptates.</p>

</div>

<div id="front">
  <p>Lorem ipsum dolor sit amet consectetur, adipisicing elit. Autem, quam similique quibusdam libero voluptatum laboriosam, sunt possimus non nobis recusandae, excepturi ex voluptates! Neque veniam, sapiente magnam fuga unde autem.
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugiat consequatur consectetur laudantium voluptatibus, iusto molestiae fugit inventore rerum, sit sed dolor ratione perferendis beatae molestias. Asperiores odio mollitia quisquam voluptates.</p>
</div>

Additional References:

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

Access the information from the text box and text area, then store it into a cookie using either jQuery or JavaScript

I need to save the text entered in a textbox within an iframe. How can I achieve this using jQuery or JavaScript? Any assistance would be greatly appreciated. ...

What is preventing me from using bracket notation with a variable to assign a property to an object?

I am a complete beginner when it comes to Vuex, and I am currently facing an issue with assigning a value to a Vuex state, specifically state.map.status.isReady. To make my code more reusable, I decided to create a function called changeMapStatus(state, k ...

Navigation bar in reactjs remains visible even after clicking on an icon button, causing a temporary issue with

I'm facing an issue with my navigation bar created using material-ui. I have an onClick function set up so that when the user clicks the icon button, the navigation redirects to a new page and then should close. However, no matter what I try, the navi ...

What is the method for retrieving a value from my Node.js module once it has been modified by an asynchronous function?

Apologies, but as a beginner developer, I'm struggling to see how this relates directly to the questions already mentioned. I have no understanding of ajax and I'm unsure how to adapt the solutions provided to my own situation. Currently, I&apos ...

Avoid saving sessions in Node.js using Express.js and Mongoose

I've recently embarked on learning node.js and have set up a Phonegap project. However, I'm facing an issue where req.session is coming up as undefined in my code: app.js const express = require('express'), routes = require('./rou ...

Is it possible to integrate Wavify with React for a seamless user experience?

For my website designs, I have been experimenting with a JavaScript library known as Wavify (https://github.com/peacepostman/wavify) to incorporate wave animations. Recently delving into the world of React, I pondered whether I could integrate Wavify into ...

When encountering a TypeError where it is not possible to read the property 'data' of an undefined value, the result returned may be

How can I retrieve a value when selecting an element from an array that doesn't have an index? For instance: var series = [{data: [10]}, {data: []}, {data: []}, {data: []}, {data: [10]}, {data: []}, {data: [10]}, {data: []}, {data: []}, {d ...

Transferring information from offspring to parent

Greetings! I'm currently getting my feet wet with React and finding myself stuck on an issue regarding passing states. Is it possible for me to pass a child state to a parent component in order to selectively render other child components? ...

Move on to the following iteration within a (Typescript) .forEach loop by using setTimeout

Within my array, I have a list of image URLs that I need to update the src attribute of an img tag every 10 seconds. To achieve this, I am using a forEach loop which includes a setTimeout function that calls a DOM manipulation function (replaceImage) as sh ...

Can you explain the distinction between using inline-block and inline-table display properties?

It appears that these display selectors are indistinguishable based on my assessment. According to the Mozilla CSS documentation: inline-table: The inline-table value doesn't have a direct HTML equivalent. It functions like a <table> HTML elem ...

Looking to retrieve a cookie within Vue Router in Vue 3? Utilize the following approach within your router's `index.js

Scenario: Developing a Vue3 app with express as the API backend. Express utilizes express-sessions to create a server-side session that is transmitted to the browser and received in subsequent requests. I am in the process of implementing a route guard to ...

Remove any words that are not included in the specified list

Here is the code snippet to achieve the desired functionality: const { words } = require("../../json/words.json") const args = message.content.split(' ') const wordss = words.filter(m=> m.includes(args)) if(args > 1 || !wordss) { ...

Using jQuery in Rails 3 to display the id of a td element

I am working with a 3x3 table that contains td elements with unique id's (id='a1'...id='c3'). I want to enable the user to click on any of these 9 td elements and receive an alert displaying the id of the clicked td. Below is my C ...

Which callback function is best suited for handling the response in an XMLHttpRequest and rendering it on the webpage?

Upon a user action on the page, an AJAX request is made to my Node.js Express server to send data. Here's what happens next: router.post('/', function(req, res){ //user authentication first, then inside that callback res.redirect('/d ...

Tips for making a fluid DIV expand to fit the entire width of the page

My layout features fixed-width sidebars on the left and right, with a fluid main content area that fills the space in between using float:left. Here's an example: #left-sidebar {width: 200px;} #right-sidebar {width: 300px;} #main-content {margin-left ...

Issue encountered when toggling flip switch in Jquery Mobile

I am trying to create a calculator for my app using Jquery Mobile, but I am facing an issue with the flip toggle switch. Here is my script: <script type="text/javascript"> function dosis() { $peso = $('#peso').get(0).value $dosis = ...

Disabling the shadow when setting the face color in Three.js

When creating geometric objects in my project, I am randomly setting colors on the faces: // Material used to create the mesh var material = new THREE.MeshLambertMaterial({ color: 0xffffff, ambient: 0xffffff, vertexColors: THREE.FaceColors}) function ad ...

Move the Material UI popover to the clicked icon's position

I am looking to create a popover similar to the image linked below. When the icon is clicked, I want the popover to display with the same user interface. https://i.sstatic.net/yvKjF.png Here is the code snippet that I have been using: {showPopOver &&a ...

The compiler option 'esnext.array' does not provide support for utilizing the Array.prototype.flat() method

I'm facing an issue with getting my Angular 2 app to compile while using experimental JavaScript array features like the flat() method. To enable these features, I added the esnext.array option in the tsconfig.json file, so the lib section now includ ...

software tool for managing state transitions

Can anyone recommend a superior javascript library for workflows? Right now, I'm utilizing Joint JS, but I require something with a more visually appealing interface (users tend to prefer that). ...