65

Is there a way to scroll down to an anchor link using jQuery?

Like:

$(document).ready(function(){
  $("#gotomyanchor").click(function(){
      $.scrollSmoothTo($("#myanchor"));
  });
});

?

revelt
  • 2,312
  • 1
  • 25
  • 37
dynamic
  • 46,985
  • 55
  • 154
  • 231

12 Answers12

122

Here is how I do it:

    var hashTagActive = "";
    $(".scroll").on("click touchstart" , function (event) {
        if(hashTagActive != this.hash) { //this will prevent if the user click several times the same link to freeze the scroll.
            event.preventDefault();
            //calculate destination place
            var dest = 0;
            if ($(this.hash).offset().top > $(document).height() - $(window).height()) {
                dest = $(document).height() - $(window).height();
            } else {
                dest = $(this.hash).offset().top;
            }
            //go to destination
            $('html,body').animate({
                scrollTop: dest
            }, 2000, 'swing');
            hashTagActive = this.hash;
        }
    });

Then you just need to create your anchor like this:

<a class="scroll" href="#destination1">Destination 1</a>

A demo is also available here: http://jsfiddle.net/YtJcL/

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
hanoo
  • 4,175
  • 2
  • 26
  • 19
  • 3
    What's the point of checking to see the lowest point to which you can scroll? Do some browsers mess up if you try to scroll below the last window-height? Chrome doesn't seem to mind; i.e., setting `scrollTop: veryHighNumber` just takes you to the bottom of the page. – Andrew Jun 02 '13 at 05:40
  • 6
    I guess the animation would be cut off pretty hard because jQuery tries to animate the full specified length and the browser just stops scrolling when the window reaches the end. – Strayer Jun 26 '13 at 15:10
  • 1
    How would one go about making the anchor offset (lets say 50px) from the top of the page using this technique. – Jamie Collingwood Dec 12 '13 at 20:13
  • 3
    @JamieCollingwood dest=$(this.hash).offset().top-50; I think this would do the trick. – Kyle Jan 13 '14 at 00:57
  • Nice solution! Just noting for the record that the link needs to target an element with an `id`, not an anchor `name`. I assumed the latter and got really frustrated with this before I looked at your Fiddle more closely. Cheers! – Brendan Feb 05 '14 at 01:35
  • I might add that adding a `$('html,body').stop()` command right before the animate is extremely helpful for preventing a buildup of animation queues. I used this in smooth scrolling for a table of contents on the page, and clicking several at once very quickly caused the window to then scroll to each destination over a period of several seconds. – SventoryMang Feb 26 '14 at 21:08
  • I've tried this on my pc, but it is not working. on jsfiddle it is working. i tried with a lot of JQuery versions, than i copied the code from result in jsfiddle, but it is directly going to the anchor. why? – artur99 Mar 24 '14 at 19:31
  • is there anyway to add class top active section ? – Accore LTD Apr 19 '14 at 12:31
  • be sure to use `.on("click touchstart" , function(){....` instead of `.click(` this is 2014 – Toskan Dec 22 '14 at 22:24
49

I would use the simple code snippet from CSS-Tricks.com:

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});

Source: http://css-tricks.com/snippets/jquery/smooth-scrolling/

mark.monteiro
  • 2,609
  • 2
  • 33
  • 38
David
  • 491
  • 3
  • 3
  • this is probably the better solution if you want all your in-page anchor links to scroll-animate without any frills etc. Otherwise jQuery.scrollTo has a lot of cool other tricks (check their demo page) – Zach Lysobey Dec 16 '11 at 15:57
  • This is a pretty awesome drop-in solution – Talk nerdy to me Mar 06 '15 at 04:35
  • In principle - use **code** not **links** - http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers – Mars Robertson Aug 04 '15 at 11:35
  • Note that the pathname attribute doesn't contain any of the get variables, so if your url only differs by get variables, this code won't work. – Jay K May 31 '16 at 20:00
  • 2
    Uhhh, no idea how this snippet could possibly work. Should be `$('a[href*="#"]:not([href="#"])')` – Dalin Oct 26 '20 at 14:51
42

Best solution I have seen so far: jQuery: Smooth Scrolling Internal Anchor Links

HTML:

<a href="#comments" class="scroll">Scroll to comments</a>

Script:

jQuery(document).ready(function($) {
    $(".scroll").click(function(event){     
        event.preventDefault();
        $('html,body').animate({scrollTop:$(this.hash).offset().top}, 500);
    });
});
Hanna
  • 10,315
  • 11
  • 56
  • 89
aruizca
  • 1,891
  • 1
  • 19
  • 13
12

jQuery.scrollTo will do everything you want and more!

You can pass it all kinds of different things:

  • A raw number
  • A string('44', '100px', '+=30px', etc )
  • A DOM element (logically, child of the scrollable element)
  • A selector, that will be relative to the scrollable element
  • The string 'max' to scroll to the end.
  • A string specifying a percentage to scroll to that part of the container (f.e: 50% goes to * to the middle).
  • A hash { top:x, left:y }, x and y can be any kind of number/string like above.
Mark Biek
  • 146,731
  • 54
  • 156
  • 201
  • is this a plugin? because i tried it and nothing happened.. i used this: $.scrollTo("#addNewUA",800, {easing:'elasout'}); – dynamic Nov 16 '10 at 19:55
  • 3
    Yes, it's a plugin so you'll need to download it and include it. It's pretty lightweight though and the functionality is fantastic. (NB: I don't have any personal connection beyond using it in a lot of sites) – Mark Biek Nov 16 '10 at 20:03
4

Here's the code I used to quickly bind jQuery scrollTo to all anchor links:

// Smooth scroll
$('a[href*=#]').click(function () {
    var hash = $(this).attr('href');
    hash = hash.slice(hash.indexOf('#') + 1);
    $.scrollTo(hash == 'top' ? 0 : 'a[name='+hash+']', 500);
    window.location.hash = '#' + hash;
    return false;
});
teh_senaus
  • 1,394
  • 16
  • 25
3

I wanted a version that worked for <a href="#my-id"> and <a href="/page#my-id">

<script>        
    $('a[href*=#]:not([href=#])').on('click', function (event) {
        event.preventDefault();
        var element = $(this.hash);
        $('html,body').animate({ scrollTop: element.offset().top },'normal', 'swing');
    });
</script>
Justin
  • 26,443
  • 16
  • 111
  • 128
2

Try this one. It is a code from CSS tricks that I modified, it is pretty straight forward and does both horizontal and vertial scrolling. Needs JQuery. Here is a demo

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top-10, scrollLeft:target.offset().left-10
        }, 1000);
        return false;
      }
    }
  });
});
Piacenti
  • 1,188
  • 10
  • 9
1

Using hanoo's script I created a jQuery function:

$.fn.scrollIntoView = function(duration, easing) {
    var dest = 0;
    if (this.offset().top > $(document).height() - $(window).height()) {
        dest = $(document).height() - $(window).height();
    } else {
        dest = this.offset().top;
    }
    $('html,body').animate({
        scrollTop: dest
    }, duration, easing);
    return this;
};

usage:

$('#myelement').scrollIntoView();

Defaults for duration and easing are 400ms and "swing".

Community
  • 1
  • 1
mpen
  • 272,448
  • 266
  • 850
  • 1,236
1

works

$('a[href*=#]').each(function () {
    $(this).attr('href', $(this).attr('href').replace('#', '#_'));
    $(this).on( "click", function() {

        var hashname = $(this).attr('href').replace('#_', '');

        if($(this).attr('href') == "#_") {
            $('html, body').animate({ scrollTop: 0 }, 300);
        }
        else {
            var target = $('a[name="' + hashname + '"], #' + hashname),
                targetOffset = target.offset().top;
            if(targetOffset >= 1) {
                $('html, body').animate({ scrollTop: targetOffset-60 }, 300);
            }
        }
    });
});
0

I used in my site this:

$(document).ready(function(){
$('a[href^="#"]').on('click',function (e) {
    e.preventDefault();

    var target = this.hash,
    $target = $(target);

    $('html, body').stop().animate({
        'scrollTop': $target.offset().top
    }, 1200, 'swing', function () {
        window.location.hash = target;
    });
});

});

You could change the speed of the scrolling changing the "1200" i used by default, it works fairly well on most of the browsers.

after putting the code between the <head> </head> tag of your page, you will need to create the internal link in your <body> tag:

<a href="#home">Go to Home</a>

Hope it helps!

Ps: Dont forget to call:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>

Nahomy Atias
  • 193
  • 1
  • 2
  • 6
0

I used the plugin Smooth Scroll, at http://plugins.jquery.com/smooth-scroll/. With this plugin all you need to include is a link to jQuery and to the plugin code:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript" src="javascript/smoothscroll.js"></script>

(the links need to have the class smoothScroll to work).

Another feature of Smooth Scroll is that the ancor name is not displayed in the URL!

Zach Barham
  • 457
  • 1
  • 8
  • 18
0

I hate adding function-named classes to my code, so I put this together instead. If I were to stop using smooth scrolling, I'd feel behooved to go through my code, and delete all the class="scroll" stuff. Using this technique, I can comment out 5 lines of JS, and the entire site updates. :)

<a href="/about">Smooth</a><!-- will never trigger the function -->
<a href="#contact">Smooth</a><!-- but he will -->
...
...
<div id="contact">...</div>


<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
    // Smooth scrolling to element IDs
    $('a[href^=#]:not([href=#])').on('click', function () {
        var element = $($(this).attr('href'));
        $('html,body').animate({ scrollTop: element.offset().top },'normal', 'swing');
        return false;
    });
</script>

Requirements:
1. <a> elements must have an href attribute that begin with # and be more than just #
2. An element on the page with a matching id attribute

What it does:
1. The function uses the href value to create the anchorID object
   - In the example, it's $('#contact'), /about starts with /
2. HTML, and BODY are animated to the top offset of anchorID
   - speed = 'normal' ('fast','slow', milliseconds, )
   - easing = 'swing' ('linear',etc ... google easing)
3. return false -- it prevents the browser from showing the hash in the URL
   - the script works without it, but it's not as "smooth".

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Dawson
  • 7,567
  • 1
  • 26
  • 25