Aurore
Aurore

Reputation: 746

scroll step is different in Firefox - with mouse wheel

I'm making a website with huge text on screen & I would like to be able to scroll two divs at the same time. So this part is working. I'm actually able to scroll the divs but the jumps are really too huge on the #back div. (they seems to actually be the same as the window height (so maybe you need to have the snipped full screen to fully understand what I mean)).

UPDATE: after a bit of testing with a friend, the issue appears to be with firefox on windows. It's working just fine on mac & linux. here is a fiddle so you can see with a increased height

Here are two gif so maybe you see the weird effet. each page movement = one scrollwheel down on my mouse (also it's working just fine with a trackpad since it's not a mouse wheel). enter image description here

VS when I remove one of the two overflow in my css, my following black square stops working, but the scroll is normal again : enter image description here


IMPORTANT EDIT : This is an issue in firefox but it seems to be working correctly in chrome & Brave. I'm still looking for a way to make it work nonetheless.

So, I noticed that this happens when I set two overflows in the css, actually, if you remove one, the script doesn't work anymore but the scroll bug is stopping too. Here is the example with 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>

Upvotes: 0

Views: 493

Answers (1)

Louys Patrice Bessette
Louys Patrice Bessette

Reputation: 33933

EDIT

What is below is not an answer to the question, which is now more specific about a FF behavior more than a scroll sync between the two divs.

For scroll sync

That is more about some maths... And also which values to use.

You have to calculated a percentage of what has been scrolled from what is scrollable. Here is the key! What is scrollable is not the whole height of the element because there is always a part that is visible.

That make three values to consider about #back:

  • A: the visible part of the div, which you get using .innerHeight()
  • B: the amount of scrolled pixels, which you get with .scrollTop()
  • C: the full height of the div, including the parts already scrolled (above the top) and the one to be scrolled (below the bottom). That is the scrollHeight property.

So to obtain the right percentage, the formula is: B/(C-A).

Then, use this percentage on the #front "scrollable pixels", which again, is the full height minus the visible height.

And there you go!

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)
  
  console.log("Scrolled % BACK:", percentage_back, "FRONT:", percentage_front)
  
  // 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
}
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;
}

/* Just for this demo here... to limit the SO console's height */
.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>

Some documentation:

Upvotes: 1

Related Questions