I have 5 anchors on my html page. Is there any way that the page scrolls automatically to the next anchor (#) by a single Mouse-wheel scroll? Is there a way that it happens regardless of the anchor's name? just to the next anchor.
-
Mousewheel click or mousewheel scroll? – Derek 朕會功夫 Sep 15 '14 at 01:17
-
You could use the `window.scroll()` [function](http://api.jquery.com/scroll/) along with the `.next()` [function](http://api.jquery.com/next/) and the `.scrollTop()` [function](http://api.jquery.com/scrolltop/) – Jake Sep 15 '14 at 01:27
2 Answers
This works in Chrome, IE, Firefox, Opera, and Safari:
(function() {
var delay = false;
$(document).on('mousewheel DOMMouseScroll', function(event) {
event.preventDefault();
if(delay) return;
delay = true;
setTimeout(function(){delay = false},200)
var wd = event.originalEvent.wheelDelta || -event.originalEvent.detail;
var a= document.getElementsByTagName('a');
if(wd < 0) {
for(var i = 0 ; i < a.length ; i++) {
var t = a[i].getClientRects()[0].top;
if(t >= 40) break;
}
}
else {
for(var i = a.length-1 ; i >= 0 ; i--) {
var t = a[i].getClientRects()[0].top;
if(t < -20) break;
}
}
if(i >= 0 && i < a.length) {
$('html,body').animate({
scrollTop: a[i].offsetTop
});
}
});
})();
Fiddle at http://jsfiddle.net/t6LLybx8/728/
How it works
To monitor the mouse wheel in most browsers, use $(document).on('mousewheel')
. Firefox is the oddball, and it requires $(document).on('DOMMouseScroll')
.
To get the direction of the mouse wheel (up or down), use event.originalEvent.wheelDelta
. Again, Firefox is the oddball, and you have to use -event.originalEvent.detail
.
If the direction is a negative number, you're scrolling down the page. In that case, loop through each tag beginning with the first, until its first getClientRects()
top is >= 40. (I used 40, in case the browser adds a default margin at the top of the viewport.)
If the direction is a positive number, you're scrolling up the page. In that case, loop through each tag beginning with the last, until its first getClientRects()
top is < -20. (I used -20 to ensure we move up the page.)
The delay
variable prevents the mouse wheel from scrolling too quickly. The entire function is wrapped in a closure, so delay
remains a private variable.

- 35,202
- 5
- 48
- 79
-
1@dcc, you're absolutely right. I've updated my code, and it should now work in all browsers. – Rick Hitchcock Sep 15 '14 at 13:41
-
Thank you Rick. Is there any chance to get smooth scrolling in this? The scroll jumps to the next anchor instead of scroll. – Bondsmith Sep 16 '14 at 08:22
-
Sure. You can't animate `scrollIntoView`, but you can simulate it by animating `scollTop` to the `a`'s `offsetTop`. I've updated my answer. – Rick Hitchcock Sep 16 '14 at 11:47
-
Hi @RickHitchcock, how can I put a pixel distance from the top? I have a header fixer, that is why is necessary add distance from top to window – Thallyson Dias Feb 03 '15 at 18:04
-
@ThallysonDias, not sure I understand, but you could possibly add the pixel offset here: `scrollTop: a[i].offsetTop` *+ pixel offset* – Rick Hitchcock Feb 03 '15 at 20:30
-
-
@RGilkes, see http://jsfiddle.net/t6LLybx8/202/. Does that work for you? Tested in IE11 and Chrome only at the moment. – Rick Hitchcock Aug 11 '15 at 14:59
-
-
@Kshitij, I haven't learned AngularJS, but that may be a question worth posting. – Rick Hitchcock Sep 09 '15 at 12:39
-
@RickHitchcock, In case you want to follow it, here is the [link to the question](http://stackoverflow.com/questions/32481572/auto-scroll-to-next-anchor-at-mouse-wheel-using-angularjs). – Kshitij Sep 09 '15 at 13:59
-
is it just me that scroll up dosent work the same way as down? – Rafael Herscovici Oct 20 '15 at 18:47
-
-
-
Thanks, that's the same version I'm using. Seems to work fine, so maybe it's your mouse? – Rick Hitchcock Oct 20 '15 at 18:51
-
i find that hard to believe (http://support.logitech.com/product/cordless-desktop-mx-5500-revolution) – Rafael Herscovici Oct 20 '15 at 19:31
-
No one else has mentioned an issue with scroll up, and I can't replicate it, so I don't know what could be causing the problem. – Rick Hitchcock Oct 20 '15 at 20:22
-
A few years later may-b someone can help me... I get Uncaught TypeError: Cannot read property 'top' of undefined - On this line: var t = a[i].getClientRects()[0].top; – Blue May 17 '17 at 09:13
-
@Blue, I'm surprised no one else has brought this up! That can happen if you're trying to scroll above the first anchor or beyond the last anchor. I've updated my answer to handle these cases. – Rick Hitchcock May 17 '17 at 13:12
-
@RickHitchcock Thank you for this but the proprety 'top' is still undefined.. I've been banging my head around this for the whole day and tried 100's of different things and the property still cant be read :)) I have other links on site also so is it possible to limit 's to specific class like say .custom-achor ? – Blue May 17 '17 at 20:11
-
Hmm, that I can't explain. Can you create a Fiddle? You can limit the anchors to a class by changing the `a` variable to: `var a = $('a.custom-anchor');`. – Rick Hitchcock May 17 '17 at 20:16
-
-
-
@L.Trabacchin, if the paragraph is longer than the screen height, it might not make sense to auto-scroll. Alternatively, you could exclude that particular paragraph within the logic. – Rick Hitchcock Dec 12 '17 at 21:53
-
Instead I was thinking about inspecting if the scroll will cause the next element to enter the scroller and if it does do the autoscroll, instead let the default scroll behaviour. But i haven't implemented that yet, so i can't know if there are flaws in my thinking... – L.Trabacchin Dec 12 '17 at 22:04
-
That's certainly doable, and it shouldn't take too much adjustment of my code to accomplish that. – Rick Hitchcock Dec 12 '17 at 22:59
let's say you have array of IDs.then you can do something like...
var ancherList = ["id1","id2","id3"];
var currentPosition = null;
var mousewheelevent = 'onwheel' in document ? 'wheel' : 'onmousewheel' in document ? 'mousewheel' : 'DOMMouseScroll';
$(document).on(mousewheelevent,function(e){
var scrollToAncher function (id,speed){
spd = speed ? "slow" //deafult value for the animation speed
var ancherTag = $("a[name='"+ id +"']");
$('html,body').animate({scrollTop: ancherTag.offset().top},spd);
}
e.preventDefault();
var delta = e.originalEvent.deltaY ? -(e.originalEvent.deltaY) : e.originalEvent.wheelDelta ? e.originalEvent.wheelDelta : -(e.originalEvent.detail);
if (delta > 0){
console.log("up")
//check your current position and target id
switch(currentPosition){
case null :
case ancherList[0] :
scrollToAncher(ancherList[1]);
currentPosition = ancherList[1];
break;
case ancherList[1] :
currentPosition = ancherList[2];
scrollToAncher(ancherList[2]);
break;
case ancherList[2] :
currentPosition = ancherList[0];
scrollToAncher(ancherList[0]);
break;
}
} else {
console.log("down")
//do the same for mouse wheel down
}
});
code ain't tested.sorry if there was syntax error

- 3,253
- 1
- 15
- 34