Content flicker/jump on infinite scroll/loop
Asked Answered
M

4

9

I am looking for help / a point in the right direction / or a solution for a flicker/jump, when scrolling on a looping/infinite website, which can be seen in this fiddle.

What seems to be causing the jump is:

"$(window).scrollTop(half_way - child_height);", and what could also be a Chrome windows scrollTop bug, but it is happening in all browsers at the moment.

If I remove "- child_height" there is no longer a flicker but the page no longer scrolls correctly, which can be seen in this fiddle.

Also, on the very first scroll the right hand column jumps up by three boxes - also because of 'half_way', which I can fix by giving it a "bottom: -600px;"

The full code:

http://jsfiddle.net/djsbaker/j3d8r/1/

var num_children = $('#up-left').children().length;
var child_height = $('#up-left').height() / num_children;
var half_way = num_children * child_height / 2;
$(window).scrollTop(half_way);

function crisscross() {
    $('#up-left').css('bottom', '-' + window.scrollY + 'px');
    $('#down-right').css('bottom', '-' + window.scrollY + 'px');
    var firstLeft = $('#up-left').children().first();
    var lastLeft = $('#up-left').children().last();
    var lastRight = $('#down-right').children().last();
    var firstRight = $('#down-right').children().first();

    if (window.scrollY > half_way ) {

        $(window).scrollTop(half_way - child_height);
        lastRight.appendTo('#up-left');
        firstLeft.prependTo('#down-right');

    } else if (window.scrollY < half_way - child_height) {

        $(window).scrollTop(half_way);
        lastLeft.appendTo('#down-right');
        firstRight.prependTo('#up-left');
    }
}

$(window).scroll(crisscross);
Mandell answered 30/1, 2013 at 11:29 Comment(2)
To avoid flicker you need to i) Clone the parent element you're modifying. ii) Modify the cloned version iii) Replace the original version with the modified cloned version. Sorry, couldn't actually get it working in fiddle. (You'll need to change from using IDs to using classes as a first step.)Withdraw
Ahh, ok, great thanks. I tried to use clone, my first time using it, but had problems removing them. I will try again.Mandell
W
5

Okay - here is a 'working' version - and by works I mean it less flickery than before. I thought it was flicker free, and it was when I was on battery power, but plugged into the mains and the CPU is fast enough to get flicker.

As I mentioned, to get rid of the flicker you need to clone the objects, manipulate them and then replace them into the DOM, rather than just manipulating the DOM directly.

I did this by getting the contents of <div id="content"> manipulating them and then replacing them into that <div>.

Also, it's a good idea to only find things in the DOM once, and from then on use a reference to that object rather than searching repeatedly. e.g.

var leftSide = $(clone).find('.up-left');
....
lastRight.appendTo(leftSide);
....
 $(leftSide).css('bottom', '-' + window.scrollY + 'px');

rather than:

lastRight.appendTo('#up-left');
$('#up-left').css('bottom', '-' + window.scrollY + 'px');

Searching the DOM is relatively slow, and so storing references can improve performance/reduce flicker.

Storing the object also makes the code easier to understand (imho) as you can easily see that you're referencing the same thing, rather than possibly different things.

Withdraw answered 2/2, 2013 at 1:4 Comment(4)
Ahh, looks like I was doing clone completely wrong, and thank you very much for the explanation - this is a great help. I am getting a flicker on the left hand column now, right one is now fine with your solution (am using Chrome on Windows). It is beautiful on Firefox Windows.Mandell
Very strange though that Chrome on windows would be having issues while chrome on mac is fineMandell
Will take your answer as it answers the question perfectly. It looks like Window Chrome might still have a scrollTop bug, which I will try to find a solution for.Mandell
I found by playing with the minus top it seems to fix the problem on chrome windows: jsfiddle.net/wkWVy/6Mandell
S
1

I still get flickering in chrome on windows with Danack solution. For this site I would control all the scrolling (you already scroll manually one of the sides), and give elements absolute positions.

Or if you insist on using the browser scrolling, may be use animations: animate the height of the last elements till 0px then use appendTo, and then animato from 0px to the normal height...

Shaeffer answered 2/2, 2013 at 2:5 Comment(5)
Yeah, same on mine (using Chrome on windows). I tried an empty hidden div that was at 0 then would expand each time but couldn't seem to get it working. I am using a small arsenal though as this is all quite new to me. Give every box absolute positions?Mandell
in css, position:absolute; then api.jquery.com/offset and taking over control over scroll from the browser #5802967 api.jquery.com/event.preventDefaultShaeffer
also i learned something new, didn't know you could throw stuff aroud the DOM using el.prependTo()Shaeffer
Yeah - it's actually still a little flickery on my computer now I'm on mains power. It was flicker free only when on battery and so the CPU was running slower.Withdraw
Works like a dream on my Firefox, strange Chrome is a pain. offset and prevent default, once again two new things for me to play with...I think Sunday afternoon with be learning curve :)Mandell
T
1

This might be a long shot, but I had the same flickering when working with infinitescroll, and ended up using imagesLoaded.I ended up appending the additional images (now loaded) with a fade in, and that prevented them from flickering because of the fact they were loaded.

So maybe by using the imagesloaded - or a callback on the images, you can solve the flickering. It does decrease the speed though. I can image that if you want to scroll through everything as fast as possible, this might not be the solution. Good luck!

Thermel answered 4/2, 2013 at 15:11 Comment(1)
Thanks, will give that a try. I think my ideal would be that users didn't scroll through the website like they were being sponsored, but I guess I can't stop them from doing so .Mandell
O
1

A solution would be to not use the native scrolling functionality but to simulate scrolling. This would be done by setting the overflow of your content to "hidden" in addition with capturing the "mousewheel" event on it and triggering some action when it is called. I started to try this out here (using MooTools instead of jQuery since I'm more fimilar with it). It's currently just "working" on the left side by altering the margin-top of the first element.

My next steps would be:

  • Check if the negative margin-top of the first element is bigger than the height of it and move it to the right side if so.
  • Same logic for the last box on the right side with a negative margin-bottom.

This has some downsides, though. Simulating scrolling doesn't feel as natural as the native scrolling functionality and clicking the mousewheel doesn't work. These might be solveable but it would require some more coding to get it to work smoothly. Anyway, in the end you would have a solution without any flickering and with no sticky scrollbar at the side (An idea for a replacement could be a small area on the side that triggers the scrolling on mouseover).

Oldtimer answered 6/2, 2013 at 23:8 Comment(1)
Thanks for the tips. The no sticky scrollbar is a very nice solution, currently it jumps around midway and is unusable if a user scrolls using it.Mandell

© 2022 - 2024 — McMap. All rights reserved.