jQuery “animate scrolltop” only works once in Opera Mobile

Here’s something frustrating that we encountered today. With jQuery we created a smooth scroll from a link to an anchor point on the same page using animate() and scrollTop. The problem is that Opera Mobile for Android has a nasty habit of failing to work if the user manually scrolls the page or has clicked the link once already.

Lots of tutorials recommend the following for creating a smooth, scrolling link to an anchor point:

<a href="#footer" class="skip">Go to the footer</a>
...
...
...
<div id="footer">Here's the footer</div>

Here’s the jQuery that makes it work:

$(document).ready(function() {
	$(".skip").click(function(event) {
		event.preventDefault();
		$("html, body").animate({scrollTop:$(this.hash).offset().top}, 800});
	});
});

Now, based on the above here’s our fix for Opera Mobile:

$(document).ready(function() {
	$(".skip").click(function(event) {
		event.preventDefault();
		var theHash = this.hash;
		var test = $(window).scrollTop();
		$("html, body").animate({scrollTop:$(this.hash).offset().top}, 800, function() {
			// If the scroll position hasn't changed by the time this callback happens, then change location.hash manually
			if ($(window).scrollTop() == test) {
				location.hash = theHash;
			}
		});
	});
});

It’s not ideal, but it’s better than the link not working at all. The drawbacks are as follows:

1) In Opera Mobile despite the animation not happening under certain circumstances, the delay of 800ms still happens before the callback occurs and location.hash updates.

2) Changing location.hash manually will affect the back button in your application, although not necessarily in a negative way.

3) If the original effect fails, the fallback will jump abruptly to the anchor point without scrolling smoothly, but that goes without saying really.

Leave a reply

(won't be published)
Email us Web enquiry form