6

I've created some divs fading in with jQuery, I have a problem if the user scrolls a bit down though. If you are not at the top of the page, it will always jump to the bottom when a new div fades in.

Here's my code:

<style>
#overflowwrap {
   overflow:hidden !important;
}
</style>

<div id="overflowwrap">
   <div id="five" style="display: none;">a lot of content</div>
   <div id="four" style="display: none;">a lot of content</div>
   <div id="three" style="display: none;">a lot of content</div>
   <div id="two" style="display: none;">a lot of content</div>
   <div id="one" style="display: none;">a lot of content</div>
</div>

<script>
$('#overflowwrap').css('max-height',$(window).height());

$("#one").fadeIn(500);
setTimeout( function show() {
   $("#two").fadeIn(500);
}, 3000);
setTimeout( function show() {
   $("#three").fadeIn(500);
}, 6000);
setTimeout( function show() {
   $("#four").fadeIn(500);
}, 9000);
setTimeout( function show() {
   $("#five").fadeIn(500);
}, 12000);
</script>

Update: Example fiddle: https://jsfiddle.net/6qj1hbp0/1/

This wouldn't be a problem, if this was the only element on a page and the user couldn't scroll. However, it's integrated on another site (survey software), so the user is able to scroll.

Is there anything I can do to prevent the site from jumping to the bottom?

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
Jakob
  • 59
  • 2
  • I would replace every `function show() {` with just `function () {`. There is no need to add a name to that function, maybe that is causing the issue? If not, could you reproduce your problem in a JSfiddle, Codepen, or any other of your chosing? – pablito.aven Mar 03 '17 at 19:03
  • On the other hand, I would rather use callback function of `fadeIn` instead of so many `setTimeout`s. Example: `$('#one').fadeIn( 500,function(){$('#two').fadeIn( 500,function(){//etc//} ) })` – pablito.aven Mar 03 '17 at 19:05
  • Here you'll see the effect, if you scroll down after "a lot of content 3" faded in: https://jsfiddle.net/jakob_o/Ldjtnx2w/1/ Actually, I've just noticed that it only jumps in Google Chrome. Firefox and IE works fine. Do you have any idea how to fix it in Chrome? – Jakob Mar 04 '17 at 18:34
  • BTW: Replacing "function show() {" didn't help. @pablito.aven – Jakob Mar 04 '17 at 18:42
  • 2
    Im using Chrome and the fiddle does not jump. – Roy Bogado Mar 10 '17 at 17:43
  • 1
    @Jakob I'm not seeing any jump in chrome. – Michael Coker Mar 10 '17 at 17:48
  • May be you need something like that: https://stackoverflow.com/questions/5688362/how-to-prevent-scrolling-on-prepend and https://stackoverflow.com/questions/9834143/jquery-keep-window-from-changing-scroll-position-while-prepending-items-to-a-l ? – Tarwirdur Turon Mar 10 '17 at 17:49
  • You have to wait until `content 3` fades in, and then scroll a bit to the bottom, when next content fades you will see the glitch. I had to try a couple of times but I saw it happen a few – pablito.aven Mar 10 '17 at 20:04
  • @Jakob I have opened a bounty for this question, please confirm if any answer solves your problem so I give him the bounty. – pablito.aven Mar 10 '17 at 20:06
  • @Jakob do you need previous divs to be hidden on new fadeIn() or you need to keep them as well adding into bottom but scroll fix on newly added div? – Abhinav Mar 17 '17 at 13:28
  • Thanks @pablito.aven. I've posted a new answer with a solution that fixed the issue. All other answers here on StackOverflow would require changing the functionality. – Jakob Mar 17 '17 at 16:27

6 Answers6

3

Try a different approach.

Instead, of display: none on every element, try opacity: 0;

Then instead of:

setTimeout( function show() {
    $("#two").fadeIn(500);
    }, 5000);

use:

setTimeout( function show() {
    $("#two").addClass('is-visible);
}, 5000);

and add:

.is-visible { opacity: 1 !important; }

within your <style> tags.

ianp
  • 123
  • 6
1

you cannot “freeze” scroll, but you can read and change the scroll position, especially because you are using jQuery.

My solution consists in saving the current position of the scroll immediately before the fadeIn instruction then reassign the same value immediately after, with this function:

function fadeInElement(id, time) {
  var currentScroll = $(window).scrollTop();
  $('#' + id).fadeIn(time);
  $(window).scrollTop(currentScroll);
}

Then you may call the same function several times with different ids and duration time, something like this:

fadeInElement('one', 500);

or this:

setTimeout(function() {
    fadeInElement('two', 500);
}, 5000);

You may look a working example on CodePen or on JSFiddle

DanieleAlessandra
  • 1,380
  • 1
  • 12
  • 21
0

In short, the easiest thing you can do is hide the previous div every time you show a new one.

https://jsfiddle.net/6qj1hbp0/2/

$("#one").fadeIn(500);
setTimeout( function() {
  $("#one").hide();
  $("#two").fadeIn(500);
}, 3000);
setTimeout( function() {
  $("#two").hide();
  $("#three").fadeIn(500);
}, 6000);
setTimeout( function() {
  $("#three").hide();
  $("#four").fadeIn(500);
}, 9000);
setTimeout( function() {
  $("#four").hide();
  $("#five").fadeIn(500);
}, 12000);

If you want to fade from one box to the other (which creates a much smoother looking effect), you will need to do some other stuff - most notably:

  • put the boxes in order, top to bottom, #one to #five (you should do this anyways - it just makes sense congnatively)
  • set the position to absolute for each of the boxes
  • set some other styles (see the fiddle below)
  • use a special class while a box is fading in

https://jsfiddle.net/6qj1hbp0/3/

Ryan Wheale
  • 26,022
  • 8
  • 76
  • 96
0

It's simple. Just reorder your div's to the order you want to show them instead of "five, four, three, two, one". Your browser doesn't have any intention to take you to the bottom, it's just trying to keep your view point fixed on the current hash navigation. As your fading div is always above, your scrollTop will just jump to the bottom.

Another solution - if you don't want to reorder - is to remove all div id's and creating other way to recognize them, something like "data-id".

PS: look for some id's after too!

Kaique Garcia
  • 528
  • 3
  • 15
-1
  1. Do you need to restrict the overflow with hidden?

    You can just set overflow: auto and browser will automatically take care of ensuring scrollTop remains the same after the fade in. The element user is looking at after scroll will remain at the same offset. If user hasn't scrolled then it will show the latest faded element at the top

    Here's a jsfiddle: https://jsfiddle.net/sm2qaa3c/2/

    enter image description here

  2. After re-reading your comment, it seems you always want to display the latest faded div at the top. In that case you want a function to reset scrollTop to 0. You want to do it on overflowwrap not window since that's where the overflow scrolling will happen.

    ['#one', '#two', '#three', '#four', '#five'].forEach((id, idx) => {
        setTimeout(() => {
            $(id).fadeIn(500);
            $('#overflowwrap').scrollTop(0);
        }, idx * 5000);
    });
    

    enter image description here

See jsfiddle: https://jsfiddle.net/sm2qaa3c/3/

user3893988
  • 330
  • 3
  • 6
-1

Thanks for the answers, they didn't work for my purpose though.

However, I've got a solution from another forum which doesn't require changing the functionality. This seems to work:

$('#overflowwrap').css('max-height', $(window).height());
fadeIn("#one", 0)
fadeIn("#two", 5000)
fadeIn("#three", 10000)
fadeIn("#four", 15000)
fadeIn("#five", 20000)

function cs() {
console.log(document.scrollingElement.scrollTop)
}
document.scrollingElement.scrollTop = 16

function fadeIn(el, when) {
setTimeout(function show() {
var t=document.scrollingElement.scrollTop
$(el).fadeIn(500);
document.scrollingElement.scrollTop = t
}, when);

}

Here is a working example on JSFiddle: https://jsfiddle.net/6qj1hbp0/4/

Jakob
  • 59
  • 2