Scrolling to the next element

21,186

Simple solution:

To get the next container, try using next().

Basically, the <div> containers are siblings of each other, so calling .next() on one div container will give you the next.

$(".button").on("click", function(e) {
    $(document).scrollTop($(this).parent().next().offset().top);
    // $(this).parent().next() // this is the next div container.
    return false; // prevent anchor
});

http://jsfiddle.net/Pm3cj/1/

You just use $(this) to get the link object, .parent() to get the parent of the link, which is the <div>, then .next() to get the next sibling (note it will wrap automatically, so the sibling after the last <div> is the first <div>!),.offset()to get its position relative to the page,.top` to get it relative to the top border.

Then you just use $(document).scrollTop() to scroll to that location.


For a completely general solution, use:

$(".button").on("click", function(e) {
    container = $(this).parent();

    // if I am the last .container in my group...
    while (    document != container[0] // not reached root
            && container.find('~.container, ~:has(.container)').length == 0)
        container = container.parent(); // search siblings of parent instead

    nextdiv = container.nextAll('.container, :has(.container)').first();

    // no next .container found, go back to first container
    if (nextdiv.length==0) nextdiv = $(document).find('.container:first');

    $(document).scrollTop(nextdiv.offset().top);
    // $(this).parent().next() // this is the next div container.
    return false;
});

​The code basically uses container.find('~.container, ~:has(.container)') to find any sibling that has or is a .container. If nothing, then go up the DOM tree 1 step.

After it finds something which is or has a .container, it grabs it with nextdiv = container.nextAll('.container, :has(.container)').first();.

Lastly, if nothing is found, checked by nextdiv.length==0, just grab the first .container in the whole page.

Then scroll to whatever .container was grabbed.

http://jsfiddle.net/Pm3cj/3/


To animate the scroll, place the scrollTop property in an animate function:

// $(document).scrollTop(nextdiv.offset().top); // snaps to new scroll position
$('body').animate({scrollTop:nextdiv.offset().top},300); // animates scrolling

http://jsfiddle.net/Pm3cj/4/

Share:
21,186
Arrowcatch
Author by

Arrowcatch

Updated on July 05, 2022

Comments

  • Arrowcatch
    Arrowcatch almost 2 years

    I'm struggling with a jquery or javascript problem.

    It already got annoying which tells me I might think too complicated on this one.

    So my markup (simplyfied) looks like this:

    <div class="container">
        My Content
    <a href="#" class="button">scroll down</a>
    </div>
    
    
    <div class="container">
        My Content
    <a href="#" class="button">scroll down</a>
    </div>
    
    
    <div class="container">
        My Content
    <a href="#" class="button">scroll down</a>
    </div>
    
    
    <div class="container">
        My Content
    <a href="#" class="button">scroll down</a>
    </div>
    

    Basically just some containers.

    Each one contains different content and a button.


    The Plan:

    1) After a click on a button the window should scroll down to the next container.

    2) The last button scrolls to the first container again. So I need a loop.

    3) The numbers of containers may change from page to page.

    EDIT: 4) The containers may not always be direct siblings to each other (see markup below)


    The Problem:

    I could get this to work by giving each container a unique ID as a target for the scroll effect.

    The problem with that is that it gets too messy quickly.

    Cant I just somehow target "the next object with the class: container", and scroll to that?


    I'm not sure if js or jquery is the right approach. My knowledge in both is somewhat limited.

    I would be really grateful for a push in the right direction.


    EDIT: The containers may not always be direct siblings of each other.

    <div class="row">
            <div class="container">
                My Content
            <a href="#" class="button">scroll down</a>
            </div>
    
    
            <div class="container">
                My Content
            <a href="#" class="button">scroll down</a>
            </div>
    </div>        
    
            <div class="container">
                My Content
            <a href="#" class="button">scroll down</a>
            </div>
    
    
            <div class="container">
                My Content
            <a href="#" class="button">scroll down</a>
            </div>
    
    <div class="row">
            <div class="container">
                My Content
            <a href="#" class="button">scroll down</a>
            </div>
    
    
            <div class="container">
                My Content
            <a href="#" class="button">scroll down</a>
            </div>
    </div>  
    
  • Ram
    Ram over 11 years
    I could get this to work by giving each container a unique ID as a target for the scroll effect. The problem with that is that it gets too messy quickly.
  • Arrowcatch
    Arrowcatch over 11 years
    Hi ronalchn, thank you for your answer. Interesting approach. Unfortunately Im afraid I oversimplified my markup to present it here, because the containers are not always direct siblings of each other. I've updated the question accordingly. Sorry for the trouble, I simply wasn't aware that this might cause problems. Thanks a ton for your efforts!
  • ronalchn
    ronalchn over 11 years
    Added general solution (adds 3 statements) - it is even more general than the structure you added to your solution, it will work with any page structure!
  • Arrowcatch
    Arrowcatch over 11 years
    Hey ronalch, Wow! Amazing, thank you for your help. I will implement it tomorrow but looks like its working neatly. Its only a little confusing if you dont have a scrolling animation. I thought about using .animate() for this but I'm not sure where to put it without messing up your script. Is that possible? Thanks a ton! Very impressive!
  • ronalchn
    ronalchn over 11 years
    just have to modify the line doing the scrolling, and put the property into an animate function, as shown above.
  • Arrowcatch
    Arrowcatch over 11 years
    Hi ronalchn! Worked absolutely perfect! Absolutely impressive! Thank you very much!!! Oh and I really apreciated the "//comments". Helped me a lot with my understanding. Out of curiosity: How long did it take you to learn all that?
  • ronalchn
    ronalchn over 11 years
    I don't remember all the functions, I just know what can be done, and what kind of functions might be used. So I just do some quick searches on the things I don't know or remember.
  • Arrowcatch
    Arrowcatch over 11 years
    Hi @ronalchn ! Just a quick followup question: How would you add a little margin of say 5px to the top-edge of the window? (so the container have some spacing between their top-edge and the top-edge of the screen, after the scrolling) Is there a jquery trick I should look at? Thanks once more. Can hardly tell you hom much you helped me! :-)
  • ronalchn
    ronalchn over 11 years
    if you want a margin on the page, look at <body style="top-margin: 4px"
  • Marco Faustinelli
    Marco Faustinelli over 9 years
    Brilliant! Carefully crafted answer. I am studying a page from a site created by a british high-street web agency and I got here by googling one of the comments in the code: your JS sample has been taken and reused as-is ;-) Imitation is the sincerest form of flattery...