• Top
  • Reply

Building a jquery Scroll Index

If you scroll down on this page you will see a black index appear on the left. This is designed using jQuery. First of all we need to understand the blog layout and clarify the rules.


We know that our blog div element is called #blog_message. Inside this div element there are many H1, H2, H3 and HN elements. Given this rule we can use jQuery to look for and return all the HN elements we are interested in. For our case we only use H2 and H3 elements as using more will be overkill.

Populating our Index list

Our index element looks like the following to start off with

<div id='blog_index'>
        <li tag='top'>Top</li>

The search loop

Using jquery we will fetch all H2 and H3 and append the results text into a <li> into our above unorderd list. To get all these elements we use the following code:

//This function creates a list of all items
h2n = 0;
h3n = 0;
$("#message > h2, #message > h3").each(function(i){

    //Create the html DOM element in a variable
    list = $("<li>" + $(this).text() + "</li>");

    //Add the tag attribute and populate it with the current tag type (H2/H3)
    list.attr("tag", $(this).prop("tagName"));

    //Set the correct n attribute for our tag, and increment the varable hXn by one
    if ($(this).prop("tagName") == "H2") { list.attr("n", h2n); h2n++; }
    else if ($(this).prop("tagName") == "H3") { list.attr("n", h3n); h3n++; }

    //Append our record
    $('#blog_index ul').append($(list));

the .each(...) function loops through each H2 and H3 element, and appends the text of the index element into our index list. We then also add attributes such as tag and n. Where attribute tag represents what the element originally was and the attribute n represents its iteration. We also use hXn++ to add our iteration for each element type, this variable could really be added as an array but for now lets use variables.

If you want nested elements, remove the > sign from the .each element selector.


Before we can go any further we need to make our <div id='blog_index'> to use the position:fixed property, because scrolling will also scroll our div.


Now that we have a dynamic populated list, we now have to set it to scroll to its correct element. This is where the attribute n comes in handy, lets look at the code before we go any further:

//The handler for the list clicked objects
$('#blog_index ul li').live('click', function(){

    clicked = $(this);

    //Scroll to top, If the tag value of the clicked element was "top"
    if (clicked.attr("tag") == "top") 
        $('html, body').animate({scrollTop:0}, 'slow');
        return true;

    //Store the pointer to the original element that the index represents
    //Printed out this should spell "#message H2:eq(4)"
    goto_ele = $("#message " + clicked.attr("tag") + ":eq(" + clicked.attr("n") + ")");

    //Scroll to the right element
    $('html, body')
                //Go to the called elements top position
                scrollTop: goto_ele.offset().top

    return true;

The above code handlers the top function differently to the element function. If the tag attribute of the clicked element is equal to top then we just scroll our window to the top, otherwise:

We store the referencing element into the goto_ele, this variable should be interpreted like the following for 3rd H2 of the message

#message H2:eq(3)

The :eq(n) refrences the nth element type. Once we know which element we are scrolling to we simply use the .offset().top call in jQuery as a reference to scrollTo: in animate

Note we use the live event handler as we want each element appended to have this handler. If we use click there will be no handler for the new appended elements. Make sure you read up on live handlers to understand why we use this in more detail


<div id='blog_index'>
        <li tag='top'>Top</li>

<div id='message'>
    <h2>Hello Ladies and Gentlemen</h2>
    <h3>Im Back!</h3>

Hope this helps.


16th Nov 2012
© 2011 Shahmir Javaid - http://shahmirj.com/blog/30

Back to Top
All content is © copyrighted, unless stated otherwise.
Subscribe, @shahmirj, Shahmir Javaid+