4

Can anyone recommend a "best" approach for snapping the scrollbar to the top of an element when scrolling down a page?

For example, if my layout was as follows:

<div id="section-one" style="width: 100%; height: 600px;">
    Section One
</div>

<div id="section-two" style="width: 100%; height: 600px;">
    Section Two
</div>

<div id="section-three" style="width: 100%; height: 600px;">
    Section Three
</div>

<div id="section-four" style="width: 100%; height: 600px;">
    Section Four
</div>

If the user was viewing section one and began browsing down with section two beginning to take part of the browser viewport, I'd like the browser to automatically snap to the top of the next div.

I'm familiar with .scroll() and .scrollTop but a little unsure with where to go from here.

cqde
  • 675
  • 5
  • 13
  • 22
  • So you basically want the next `
    ` to jump to the top of the screen, as soon as it's within the viewport? For how long should it stay there (think about the user continues scrolling and recognizes just a moment later that the content moved to the viewport top). And what happens if the user's screen is higher than 600px, as there will be always two `
    `s visible?
    – insertusernamehere Jul 26 '12 at 23:51

3 Answers3

8

you can check if element is in wiewport with this isScrolledIntoView function created by @Scott Dowding,

And here is an example,

$(document).scroll(function() {
    $("div:not(.highlight)").each(function() {
        if (isScrolledIntoView(this)) {
           $("div").removeClass("highlight");
           $(this).addClass("highlight");
           $("body").animate({ scrollTop: $(this).offset().top }, 1000)
        }
    });
});

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();

    var elemTop = $(elem).offset().top;
    var elemBottom = elemTop + $(elem).height();

    return (elemTop <= docViewBottom) && (elemTop > docViewTop);
}​

DEMO

Community
  • 1
  • 1
Okan Kocyigit
  • 12,633
  • 18
  • 64
  • 119
  • yes, because isScrolledIntoView returns true if element in wiewport, I've changed the function, that's seems working now as you say. – Okan Kocyigit Jul 27 '12 at 00:16
  • Awesome. I guess the only thing that causes some buggy business is when the viewport shows more than one div, which causes JS to add/remove the "highlight" class multiple times to the different divs that are present. I might try finding a way to check if a div has a majority of window real estate or maybe have each div elastic, with 100% width AND height? – cqde Jul 27 '12 at 01:43
0

What you could do is set

body {
overflow:hidden
}

and have control on user interactions, let's say you have a menu if user selects a section in the menu you just animate with scrollTop to redirect to the section.

Another solution, since you have a defined height which is 600px you could calculate with scrollTop and scroll where the user is located in the document something like this...

$(window).scroll(function () { 
      console.log($(window).scrollTop());
});​

Example: http://jsfiddle.net/3STQN/

Paradise
  • 470
  • 2
  • 10
0

If multiple divs can get into the view, then you can change the function isScrolledIntoView to, let's say, isTopInTheView, or something similar. In that function you can check if the top of the div is visible, and if it is, snap that div to the top of the screen.

EDIT: and, of course, once you find the first div that fulfills the requirements, just return from the function so it can't check any more divs.

vtomic85
  • 516
  • 1
  • 9
  • 29