77

I am making an FAQ page and have buttons across the top to jump to a category (it jumps to the p tag that I use as the category label, ex. <p id="general"> for my general category). Instead of just jumping right to the category, I want to add a scroll effect. I want something like http://www.dynamicdrive.com/dynamicindex3/scrolltop.htm that scrolls to the desired part of my page. That link is a script that goes to the top of the page with a nice scrolling effect. I need something similar that will scroll to where I link to. For example, if I want to go to a misc. category, I want to just be able to have <a href="#misc">Miscellaneous</a> and have it scroll to that section of the page.

Christopher
  • 2,103
  • 4
  • 22
  • 32

8 Answers8

129

It is often required to move both body and html objects together.

$('html,body').animate({
   scrollTop: $("#divToBeScrolledTo").offset().top
});

ShiftyThomas is right:

$("#divToBeScrolledTo").offset().top + 10 // +10 (pixels) reduces the margin.

So to increase the margin use:

$("#divToBeScrolledTo").offset().top - 10 // -10 (pixels) would increase the margin between the top of your window and your element.
frzsombor
  • 2,274
  • 1
  • 22
  • 40
Brian
  • 1,307
  • 1
  • 8
  • 3
  • 19
    No semicolon here `.offset().top;` – Luqmaan Sep 20 '12 at 15:50
  • Should it not be minus 10 for a 10px margin at the top? .offset().top - 10 – ShiftyThomas May 28 '14 at 20:32
  • If you want to control the speed of scrolling, just add an duration (in ms) parameter (number as int or string) to the animate function: $('html,body').animate({ scrollTop: $("#divToBeScrolledTo").offset().top }, 2000); – Jan Jun 28 '18 at 12:41
96
$(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;
      }
    }
  });
});

Check this link: http://css-tricks.com/snippets/jquery/smooth-scrolling/ for a demo, I've used it before and it works quite nicely.

chrisweb
  • 1,428
  • 19
  • 25
FarligOpptreden
  • 5,013
  • 22
  • 23
  • Yeah, if it wasn't for the 15 characters minimum comment I would've commented on yours with: Snap! :P – FarligOpptreden Mar 12 '11 at 19:23
  • This script is the winner, but I don't know whose to choose! – Christopher Mar 12 '11 at 19:28
  • 1
    Well, seeing as I was first (by 15 seconds), I guess I deserve a win? :P As a token of gratitude I'll upvote symmet's answer for some extra rep... – FarligOpptreden Mar 12 '11 at 19:35
  • 2
    Guys, what about my (related but unjustly downvoted) question? http://stackoverflow.com/questions/28400107/jquery-bring-a-div-into-viewport maybe you will have some insight ? – yPhil Feb 09 '15 at 07:53
  • @xaccrocheur it was indeed unjustly downvoted. I posted a possible solution to your problem. – FarligOpptreden Feb 09 '15 at 18:10
  • sorry noob question. but what does this do? `if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {` – user2636556 Jun 17 '16 at 06:49
  • at least on jquery v1.12.4, the hash character on selector needs to be escaped like this: `$('a[href*=\\#]:not([href=\\#])')` – Gero Sep 09 '16 at 17:18
28

Something like this would let you take over the click of each internal link and scroll to the position of the corresponding bookmark:

$(function(){
  $('a[href^=#]').click(function(e){
    var name = $(this).attr('href').substr(1);
    var pos = $('a[name='+name+']').offset();
    $('body').animate({ scrollTop: pos.top });
    e.preventDefault();
  });
});
weltraumpirat
  • 22,544
  • 5
  • 40
  • 54
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
27

Could just use JQuery position function to get coordinates of your div, then use javascript scroll:

var position = $("div").position();
scroll(0,position.top);
JimmyJammed
  • 9,598
  • 19
  • 79
  • 146
9

if the link element is:

<a id="misc" href="#misc">Miscellaneous</a>

and the Miscellaneous category is bounded by something like:

<p id="miscCategory" name="misc">....</p>

you can use jQuery to do the desired effect:

<script type="text/javascript">
  $("#misc").click(function() {
    $("#miscCategory").animate({scrollTop: $("#miscCategory").offset().top});
  });
</script>

as far as I remember it correctly.. (though, I haven't tested it and wrote it from memory)

Stoic
  • 10,536
  • 6
  • 41
  • 60
  • 2
    – moffepoffe Nov 17 '12 at 21:25
  • I have tried a multitude (and I mean a multitude) of methods to programmatically force a scroll to top of a div inside a modal window. All failed. This one did the trick! Cheers! – RationalRabbit Apr 23 '19 at 03:49
1

I ran into the same. Saw an example using this: https://github.com/flesler/jquery.scrollTo

I use it as follows:

$('#arrow_back').click(function () {
    $.scrollTo('#features_1', 1000, { easing: 'easeInOutExpo', offset: 0, 'axis': 'y' }); 
});

Clean solution. Works for me!

Andrew Brooke
  • 12,073
  • 8
  • 39
  • 55
Paul0515
  • 23,515
  • 9
  • 32
  • 47
1

The script below is a generic solution that works for me. It is based on ideas pulled from this and other threads.

When a link with an href attribute beginning with "#" is clicked, it scrolls the page smoothly to the indicated div. Where only the "#" is present, it scrolls smoothly to the top of the page.

$('a[href^=#]').click(function(){
    event.preventDefault();
    var target = $(this).attr('href');
    if (target == '#')
      $('html, body').animate({scrollTop : 0}, 600);
    else
      $('html, body').animate({
        scrollTop: $(target).offset().top - 100
    }, 600);
});

For example, When the code above is present, clicking a link with the tag <a href="#"> scrolls to the top of the page at speed 600. Clicking a link with the tag <a href="#mydiv"> scrolls to 100px above <div id="mydiv"> at speed 600. Feel free to change these numbers.

I hope it helps!

lflier
  • 104
  • 5
  • I should remove line 2: `event.preventDefault();`. By this rule the anchor is not added to the url (in your address-bar). So, if someone copies the page.... You get it? ;) By removing that line it's fixed. Thanks :) – Bob Mar 07 '15 at 21:11
  • Yes, that's better. Thank you. That line was also preventing the script from working in Firefox. – lflier Jul 30 '15 at 23:32
1

You can also use 'name' instead of 'href' for a cleaner url:

    $('a[name^=#]').click(function(){
    var target = $(this).attr('name');
    if (target == '#')
      $('html, body').animate({scrollTop : 0}, 600);
    else
      $('html, body').animate({
        scrollTop: $(target).offset().top - 100
    }, 600);
});
nickRO87
  • 103
  • 3
  • 8