NaOH
NaOH

Reputation: 459

Odd Behaviour From jQuery Animate

I'm using jQuery's animate() function in conjunction with easing from the jQuery UI plugin to animate scrolling down my page with links in a sidebar. I'm also using it to operate a "back to top" button. You can see it live here: http://www.element17.com/

The back to top button is working perfectly, but the behaviour of the links is erratic. Sometimes it works great, and other times it either refuses to scroll, waits a second or two and then scrolls, or doesn't animate at all and just jumps down the page as if they weren't scripted in the first place.

Here's the code for the back to top button:

$('#go_up').click(function(){
  $('#main').animate({scrollTop:0}, 2000, 'easeOutExpo');
});

And here's the code for the links:

$('.scroll').click(function(){
  $('#main').animate({scrollTop:$(this.hash).offset().top}, 3000, 'easeOutExpo');
});

I've tested this in Chrome in OSX and Windows, and the behaviour is erratic in both. Can anyone suggest why this might be the case?

Upvotes: 0

Views: 121

Answers (2)

yckart
yckart

Reputation: 33408

At the first you need to prevent the default behavior from hash links (return false) and further you need to check if there's an element with the given id.

$('a[href*=#]').on('click', function() {
    var hash = $(this.hash).offset();
    if (hash) {
        $('#main').stop().animate({
            scrollTop: hash.top
        }, 3000, 'easeOutExpo');
        return false;
    }
});

UPDATE Change your links and ID's to valid ones:

  • #EN%20FLEURS -> #EN_FLEURS
  • #WWPW%202011 -> #WWPW_2011
  • #MUSEÉ%20DU%20LOUVRE -> #MUSEE_DU_LOUVRE
  • #FAIRYTALE%20ROAD -> #FAIRYTALE_ROAD

By the way

To hide your scroll to top link if not needed (e.g. at the top of your page) use this:

$(window).scroll(function () {
    if ($(this).scrollTop() !== 0) {
        $('#go_up').fadeOut();
    } else {
        $('#go_up').fadeIn();
    }
});

Hide it with css:

#go_up {display:none}

Upvotes: 2

Alex Pakka
Alex Pakka

Reputation: 9706

Your $(this.hash).offset().top does not always provide the value you expect, i.e. from the top of the #main div. If you scrolled to the bottom of the page and hit a link at the bottom, its offset().top will be relative on the screen, not absolute. Could be a negative value, for example. However, animate's scrollTop requires absolute scroll position.

One solution could be to do

$('#main').animate({scrollTop:
       $(this.hash).offset().top - $('#CONSTRUCTS').offset().top},
   3000, 'easeOutExpo');

where #CONSTRUCTS will work as the topmost element.

Depending on how dynamic your data is, you might want to replace it with anything at the top left corner of your #main.

There are many other ways to solve it.

Upvotes: 1

Related Questions