jQuery One Page Navigation Plugin

When appropriate, I am a fan of the one-page sites. I really like the ones that add smooth scrolling and highlight the navigation depending upon which part of the page you have scrolled to. Here are a few examples: Brizk Design and Crush + Lovely. I finally have a freelance project where a one-page site makes sense, so I needed to write the JavaScript to make the navigation work how I wanted.

I wanted the page to scroll smoothly when the navigation was clicked, so I used the jQuery ScrollTo plugin. I also wanted the page to automatically highlight the correct navigation section depending upon which section was scrolled to, and that was where I added my custom code.

If you want to skip ahead, you can check out the demo and download the plugin from GitHub.

The Markup

I started with an unordered list for the navigation and a bunch of sections:

<ul id="nav">
  <li class="current"><a href="#section-1">Section 1</a></li>
  <li><a href="#section-2">Section 2</a></li>
  <li"><a href="#section-3">Section 3</a></li>
</ul>

<div id="section-1">
  <strong>Section 1</strong>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor
  incididunt ut labore et dolore magna aliqua.</p>
</div>
<div id="section-2">
  <strong>Section 2</strong>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 
  incididunt ut labore et dolore magna aliqua.</p>
</div>
<div id="section-3">
  <strong>Section 3</strong>
  <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor 
  incididunt ut labore et dolore magna aliqua.</p>
</div>

The JavaScript

Then, I added jQuery, the ScrollTo plugin, and my plugin to the page:

<script src="jquery.js"></script>
<script src="jquery.scrollTo.js"></script>
<script src="jquery.nav.min.js"></script>

Finally, I just need to call my plugin on the navigation:

$(document).ready(function() {$('#nav').onePageNav();});

Options

There are a few options for this plugin:

  • currentClass: 'current'

    Class to add to the list item when the navigation item is selected
  • changeHash: false

    If you want the hash to change when the user clicks on the navigation, change this to true
  • scrollSpeed: 750

    Speed to scroll the page when the navigation is clicked

And that’s it. Check out the demo and download the plugin from GitHub.

84 Comments

dxtr

11.11.2010

great and thank you for sharing ! but it doesn’t seem to work with ie 6 - well .. i know but ...    :/ 
any idea ? ....

Trevor

11.12.2010

@dxtr-
I didn’t even test in IE6. Fixed positioning isn’t supported so you would have to make some modifications to the CSS to even get it to look correctly.

Pixi

12.05.2010

Hello,

This script is great and what I was looking for however it creates a conflict with the other scripts of my site and I don’t know how can I add noconflict? Can you help me please? Thanks in advance.

Trevor

12.05.2010

@Pixi-
What do you mean you are having a conflict? Is there a specific error?

Emil

12.09.2010

Trevor,
There is a small bug with internet explorer (all versions, including 9),

For some reason IE does not bind the ‘scroll.onePageNav’, and therefore the currentClass does not get applied when scrolling the page.

I know that there is an IE issue with binding event to absolutely positioned elements, but i did not look into it.

Trevor

12.11.2010

@Emil-
Thanks for letting me know.

VJ

12.22.2010

Hello,

When I put an external link to the menu, other than links with anchors, the script stops working and makes some other scripts stop working as well. What may be the reason of this?

Trevor

12.22.2010

@VJ-
Can you provide a link?

VJ

12.22.2010

@Trevor-
Thanks for getting back to us. We just emailed you the link. Thank you in advance.

Underlog

12.27.2010

Hi, i’m new with jquery, and i wonder what is de .do class in the jquery code, at the end of the source code of your demo, thanx!

Trevor

12.27.2010

@Underlog-
You can ignore that if you just want to use the plugin. But if you want to know just so that you understand, it is appending a paragraph to the 4th section when the link it clicked. It’s purpose was to demonstrate that the plugin would still work even if content was dynamically added.

Underlog

12.27.2010

Amazing! thank you so much!

Mark

01.05.2011

Hey,
I have a bug and dont know how do I fix it.
Im using your JS scripts and the JS scripts from “colorbox”.
An he is using “http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js”

When I use
“http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js”
it doesnt scroll to the section it jumps to it and “colorbox” is working.

And when I delete
[removed][removed]

it scrolls to the section (your part is working) but colorbox works not.

Can you or somebody else help me?

thx

Mark

01.05.2011

i meant when I delete http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js
out of my html code.

it scrolls to the section (your part is working) but colorbox works not.

Trevor

01.09.2011

@Mark-
Make sure you are using the latest version of Colorbox.

IvanB

01.10.2011

This worked like a charm! Used it in my university project. Thank you very much!

Mark

01.10.2011

Trevor, Im using the last version of colorbox.
I’ve seen you’re using too the colorbox, is’nt it?
I dont know where the problem is. I’ve also already dowloaded the latest 1.4. jquery to my pc. Maybe there are the same varaibles in your script and in colorbox which were using?

Trevor

01.10.2011

@Mark-
Do you have a link to your page? Are you getting a specific error?

Borg

01.11.2011

Hi, I got a little question.
Here they only use one menu, I want to use the script on a website with 3 menu’s, this is what I did:

$(document).ready(function() {
  $(’#nav2’).onePageNav();
$(’#nav3’).onePageNav();
$(’#nav’).onePageNav();

Now this works but sometimes if i go from lets say #nav2 to #nav1 one of the 3 links (I got 3 links each #nav) will be dead, not doing anything. Is there a better way to use multiple menu’s?

Thanks

Trevor

01.11.2011

@Borg-
Do you have a link to your page? I’m confused as to why you could have 3 separate menus.

Borg

01.12.2011

@Trevor

Thanks for quick reply,

this is the link http://www.hetstilleseizoen.be/purt/index.html

Trevor

01.12.2011

@Borg-
The requirements for your page don’t seem to really suit this plugin very well. I would write a short custom script instead to solve your problem.

Borg

01.12.2011

Again thanks for the quick reply.

Can u tell me what I did wrong and for the short code, can u give me some information? I m not that good with Jquery or Javascript. Don’t realy know how to get started at the script.

VJ

01.12.2011

Hello,

A couple of weeks ago we wrote a comment about putting an external link into the menu, it breaks the script and other scripts on the page as well. We want to find the reason of it. Maybe you can help us. You asked for our website link and we sent it by writing in your contact page. We haven’t heard from you since. Maybe you haven’t received the message. How can we give our link to you other then writing it as a comment?

Trevor

01.12.2011

@VJ-
I emailed you back on 12/26 to the email address that you submitted in the contact form. Did you not receive it?

Trevor

01.13.2011

@Borg-
Sorry, I can’t just write all of the code for you. The reason that your site doesn’t really suit the plugin is because the plugin is intended to use a single menu on the page.

VJ

01.13.2011

Sorry we just checked our spam folder as well but couldn’t find your email. Maybe we missed it somehow. Can you email us again if it is possible to this address? Thank you for your response. We appreciate it.

Alex

01.17.2011

This is awesome! Thanks so much!

Kris

01.28.2011

My menu isn’t at the top and I wanted to change the scrollTo to match my menu offset, so I added offset to the code. And it worked wonderful!

here:
  onePageNav.bindNav = function($el, $this, curClass, changeHash, scrollSpeed, navOffset)

here:
  $.scrollTo(newLoc, scrollSpeed, { offset: -navOffset,

and here:
  $.fn.onePageNav.defaults = {
  currentClass: ‘current’,
  changeHash: false,
  scrollSpeed: 750,
  navOffset: 0
  };

Now I can give the offset during the menu initiate!

Is there a way so the menu is no longer fixed after the last menu-item is reached?

Trevor

01.28.2011

@Kris-
Nice addition with the navOffset. I’m not sure what you mean by making it not fixed anymore. Can you explain in more detail?

Kris

01.30.2011

@Trevor

Nevermind the fixed question, after some thinking I believe my problem is one I have to deal with outside your plugin. But thnx for your answer!

I have an other problem and don’t know how to fix.

I want to change the highlight/ current class of the “#menu li”, when the “#menu”-top is equal to “#section”-top.

Now it looks like the highlight/ current class changes when the “#section” passes 50% of the windows height.

Can I change this?

Trevor

01.31.2011

@Kris-
You will want to modify this line:
windowHeight = Math.round($(window).height() / 2);

Kris

02.01.2011

@Trevor
Thnx, that did the trick!

I have it now like this: 

  onePageNav.getSection = function(windowPos, navOffset) {
    // edit this section for change “current”-class on scroll
    var returnValue = ‘’,
      windowHeight =  navOffset || Math.round($(window).height() / 2);
   
    for(var section in onePageNav.sections) {
      if((onePageNav.sections[section] - windowHeight) < windowPos) {
      returnValue = section;
      }
    }
    return returnValue;
  };

And if I don’t set the navOffset, it will revert to it’s normal behaviour.

Ivaylo

02.04.2011

Thanks for the script.

I ’m experiencing two problems. Firstly, the navigation links do not highlight as I scroll through the page. Also, when inspecting , I get an error ‘TypeError: Result of expression ‘divPos’ [null] is not an object.’ on line 56.

Trevor

02.04.2011

@Ivaylo-
Do you have a link to your page?

Ivaylo

02.04.2011

Sure, I posted it using the contact form.

Ivaylo

02.05.2011

Everything worked fine for me, following your advice to do the rest of IDs referenced in the anchor links. However, Opera does not highlight the navigation sections while scrolling. I tested your demo page, just in case I’d screwed something up…

Trevor

02.05.2011

@Ivaylo-
I didn’t even look at this in Opera so I can’t really vouch for what it looks like.

Olly Killick

02.15.2011

Thanks, I will be using this soon. You are a gentleman and a scholar.

Borg

02.20.2011

Hi
I want to make the content scroll but I don’t want to see a scrollbar.
So i restricted the height of the content box to 100% of the screen
and I used this  

          overflow:hidden;

to hide the scrollbar and other content but now the script won’t work anymore.
Any suggestions?

Thanks,

Borg

Borg

02.20.2011

I found this trick on the internet to make it work
put this in your css.

html {
overflow:hidden;
}

sorry for the dum question :P

Chris

02.20.2011

@kris
@Trevor

I was looking for clarity on the navOffset value.  I also have an offset menu, however when I put in the navOffset value of 250 in the jquery.nav.js file nothing changed.

Trevor

02.20.2011

@Chris-
Did you modify the jquery.nav.js file like Kris mentioned?

Chris

02.21.2011

@Trevor

Yes I modified line 26:
onePageNav.bindNav = function($el, $this, curClass, changeHash, scrollSpeed, navOffset) {


Line 34 : $.scrollTo(newLoc, scrollSpeed, { offset: -navOffset,

and Lines 116-121 : 
  $.fn.onePageNav.defaults = {
  currentClass: ‘current’,
  changeHash: false,
  scrollSpeed: 750,
  navOffset: 300,
  };

Trevor

02.21.2011

@Chris-
I think you need to do more than just that. Kris changed the onePageNav.getSection function.

Chris

02.21.2011

@Trevor
I thought that function modification was for adjusting the highlight current class execution. However, I inserted that function change too and it didn’t help with the offset problem.

Trevor

02.21.2011

@Chris-
Sorry man, I’m not sure what else Kris had to do to make those changes.

Chris

02.21.2011

@Trevor
Hey no problem.  Thank you for responding so promptly and thank you for the plugin.

Shaun of the Web

02.28.2011

Great thing. I’ve used it for my website with x and y scrolling.

Chad Kaufman

03.02.2011

Is it possible to scroll the nav so the current item is lined up with the top of the intended section?

I have a nav with large buttons and some sections with only a little content. When the section lines up with the top of the page, there are times when the nav button no longer lines up the the section that was clicked.

Notice in the example below when clicking on Nav item #4 it scrolls passed the section:

http://ckurl.org/example/

Any help to resolve this would be greatly appreciated.

Trevor

03.02.2011

@Chad Kaufman-
You will want to change this line:

$.scrollTo(newLoc, scrollSpeed, {

To account for the offset of your navigation.

max

03.07.2011

thanks for sharing this script!

Chris

03.14.2011

THIS IS AMAZING!!!

sanch3z

03.30.2011

Hi Trevor,

Great script thanks for making it available. I’ve got it working but would like to use images (up, rollover and in-state) for my navigation, I know this isn’t great for SEO but the font and colours are really important. Can you point me in the direction of how to get images working with this great script?

Sanch.

Trevor

03.30.2011

@sanch3z-
You can just use the CSS background-image property to style your navigation.

sanch3z

03.30.2011

@Trevor-

Thanks for such a speedy response. So are you suggesting a different background-image for each item in the li list?

Thanks Sanch.

Olly Killick

03.30.2011

@Sanch

I’ve used that technique here:
http://www.ollykillick.com/test

sanch3z

03.30.2011

@olly & @Trevor,

Great site and great community cheers guys ;)

Joe

04.01.2011

Hi Trevor,

does this have to be used for anchor links? I’m looking at line 52:  onePageNav.getPositions = function($this) {

I have a set of buttons which already scroll down the page using ScrollTo, I’m trying to see if this script can be modified to change the class of the buttons.

Trevor

04.01.2011

@Joe-
You could certainly change it to work with buttons.

Joe

04.01.2011

@Trevor

Thanks for a quick reply. I made my life easier by putting <a> tags inside the buttons. It works a treat.

I’m now trying to get it to work with an offset. I change the 3 lines of code as per Kris’ post in the comments, but nothing seems to change regardless of values I put in. The quest continues…

Good job though!

Joe

04.05.2011

Got this working now as I’d hope, good work.

Sadly IE is still causing a problem, I think it’s the same one mentioned by Emil further up the comments.

When the page loads (view my link on my name) IE recognises the window location and correctly applies the class. But, it does not change the class as the window scrolls.

Is there a workaround for this?

Olly Killick

04.07.2011

Hi Trevor,

I am having an issue with linking directly to a particular section of the page.
For instance if you want to link a page to a portfolio section you would use http://myportfolio.com#portfoliosection

So when it lands on the page you don’t have to scroll to the section you want.

This works fine but I noticed when you do it, it highlights the first section of the nav even though you are in a different section of the page. For instance if you copy/paste the following URL into a browser window it highlights ‘section-1’ even though you have landed in ‘section-4’:

http://trevordavis.net/play/jquery-one-page-nav/#section-4

Is there a way to detect what section you are in, not on loading the page but on entering the page without having to click the nav?

Thanks,
Olly.

Trevor

04.07.2011

@Olly Killick-
The link to my demo page you posted highlights section 4 for me.

Olly Killick

04.07.2011

Thanks Trevor. I am experiencing the problem on Opera/IE8/Firefox 4—Win XP and OSX respectively, will try on Win 7 later. It works correctly on Chrome and Safari.

Hope this helps, I’m trying to find a way around it.

Olly Killick

04.07.2011

Hey Trevor,

A firend of mine just sent me this, I’ve yet to implement but he says it works:

Hey try adding this line after the initiation of the script

$(’#nav’).onePageNav();
$(document).triggerHandler(‘scroll.onePageNav’);

Joana

04.10.2011

Hello Trevor, thank you very much for this plugin, i’ve been searching for something like this for hours!

I’m quite a newbie on this kind of stuff so sorry if i’m asking a dumb question, but i really don’t know how to solve this.

The buttons of my menu are images and i want them to change to another images. I followed your steps, i checked and compared my code with your code and even with Olly Killick’s test page, but i don’t really know where is my mistake. I’ll leave you my link so you can see what is happening: http://oupasdesign.com/cla/segunda.html . Has you can see, when in top, the correspondent button to that section is “pushed” (orange) but when i start scrolling it changes to white (the original image) and i can never see it again pushed, even if i scroll back to the same position.

Can you understand my point? :x and if so can you help me, please?

Thank you very much, and sorry for any kind of inconvenience that i may have caused.

Take care :)

Trevor

04.10.2011

@Joana-
You just need to use a descendant selector to change the images:

.current #sons {
  /* Insert styles for the highlighted link */
}

Joana

04.11.2011

Thank you Trevor! It worked in part. Now it’s giving me some kind of error, but i think that is my fault and have nothing to do with this. I’ll try to fix it somehow. Thanks! :D

Olly

04.13.2011

I wonder if, when scrolling manually you could make it snap to the section start points. Just an idea.

Trevor

04.13.2011

@Olly-
Feel free to fork the code and make that change because I don’t think that is something that I will add into the plugin.

Olly

04.13.2011

Yeah I think I’ll try my hand at a little JQuery. Thanks Trevor—I’ll post the source code somewhere if I manage to make it work.

Marlane

04.17.2011

Hi there,

I’m using your plug-in on a new project and it works pretty fine!

I was wondering if it’s planned to have an “easing” option soon (maybe working with the easing plug-in?)...
I have tried to hack your code adding an easing method line 34:

$.scrollTo(newLoc, scrollSpeed, {easing:‘elasout’}

Works.
But now, if I click my nav, the highlight on the menu on scroll doesn’t work anymore.
I don’t understand what’s going on. Do you have a clue?

Thx =)

Trevor

04.17.2011

@Marlane-
Are you getting any JS errors after clicking the link? Do you have a link to the page?

Nate

04.20.2011

I’m trying to figure out how to get this plugin to work with a logo that links back to the top of the page, much like the way they do it on the Crush+Lovely site. The logo is in an <h1> right above the <ul> with the nav items.

Trevor

04.20.2011

@Nate-
So do you have a section in the nav that also links back to the top of the page?

Nate

04.20.2011

@Trevor
No, the nav doesn’t have an item that goes to the top. The logo goes to the top of the page, where a header section is located. The first item in the nav goes to a section just below the header.

Trevor

04.20.2011

@Nate-
Ah ok. So the easiest thing to scroll to the top would be to just use the scrollTo plugin (which is required for this plugin) to just scroll the window to the top. And then you could remove the class of current on the nav if you need to.

Nate

04.21.2011

@Trevor
Thanks for taking the time to reply. I’m pretty new to jQuery (and JavaScript), so I may just be doing something wrong. This is what I have:

$(’#logo a’).click(function(){
$.scrollTo(0, 750);
$(’#nav .current’).removeClass(‘current’);
return false;
});

I think it doesn’t work because the onePageNav function is still watching the page for scrolling, and it re-adds the current class to the nearest section as the page scrolls.

Trevor

04.21.2011

@Nate-
Something like this might do it for you:

$(’#logo a’).click(function(){
  $.scrollTo(0, 750, {
    onAfter: function() {
      $(’#nav .current’).removeClass(‘current’); 
    }
  });
  return false;
});

Nate

04.25.2011

@Trevor
That fixed it! Thanks for all the help, and thanks for the great plugin.

Andrew

04.28.2011

@Trevor. Great plugin! Thanks for writing it. I have a small question about it. I have it implemented on a site I am working on and it works great, except in one regard. When you reduce the size of the window horizontally, next time you click on a navigation element it moves the main body area under the navigation. Any thoughts on how to stop this from happening? The test site is: http://andrewpautler.com/clients/page2music/

Trevor

04.28.2011

@Andrew-
Looks like it has to do with the scrollTo plugin. In the settings, it defaults to scrolling both the x & y axes. You should be able to specify just y and you should be good to go.

Andrew

04.28.2011

@Trevor. I tried setting the axis to only one dimension, but that doesn’t seem to fix it. Oh well, I’ll keep trying. Thanks for your help.

Too late, comments are closed!

Don’t worry, you can email me or contact me on Twitter.