I've had this problem, too. This is what I use and it works. It's not browser sniffing, but it's not particularly nice code, to me. It works tho, for now.
Calling scrollTop on html element in Opera 11 / IE 8 / FF 3.6 returns a number larger than zero
Calling scrollTop on html element in Chrome 10 / Flock 3.5 / Safari 5 (for Windows) returns 0
So just test that:
If the browser is Opera, you test for a number larger than 0 on scrollTop, and call scrollTop on only html, a la
var html = document.getElementsByTagName('html')[0];
var body = document.getElementsByTagName('body')[0];
$(html).animate({scrollTop:0+'px'},{'duration':1000,'easing':'swing'});
If the browser is Chrome, or Flock or Safari than scrollTop will return 0 and you test for that, acting accordingly:
$(html,body).animate({scrollTop:0+'px'},{'duration':1000,'easing':'swing'});
So, you'll set the effect on html for standards mode FF and IE (quirks should be covered, too. Ugh), and body for Chrome and Safari.
In Opera, which attempts to scroll both html and body, thus leading to mass freakishness, scrollTop returns a number greater than 0, so you call only html and you don't get the flickery nonsense.
So you can safely use both html and body when necessary, or just html when the browser is Opera.
And don't forget yer preventDefault() or that'll be another weird flicker you'll have to worry about. ;)
Hey, I'm no JS ninja, but I try hard and this works for me, and I don't have time right now to investigate it as much as I'd like, so I thought I'd post this here and help. If I'm wrong I'll hold up my hands and say it. ;) So feedback, please. :D
Tom.