Friday, July 9, 2010

Visual Navigation

There are a few sites that have a navigation menu that can highlight / change when the menu's target scrolls into view (e.g. brizk design & Crush + Lovely) . I tried to generalize the script so it would work with any site and I ended making up with this jQuery plugin.


I set up a demo page here.

Download: Uncompressed | Minified | Zipped Demo | Github

I have tested this plugin in IE8, Firefox and Chrome. Please leave me feedback if you any problems with how it works or if it doesn't work in other browsers.

Setup
  • This plugin requires jQuery in order to function properly.
  • Follow the basic templates below to set this up on your site. For more details, go to the specific section.
Default Setup
  • HTML
    <div id="sidemenu">
    <ul>
    <li><a href="#home">Home</a></li>
    <li><a href="#work">Work</a></li>
    <li><a href="#blog">Blog</a></li>
    <li><a href="#projects">Projects</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#contact">Contact</a></li>
    </ul>
    </div>
    • Change the side menu id to whatever you want, just make sure you target it with the script.
    • This side menu example will work with the plugin's default settings. See the alternate example of a different layout.
  • CSS
    #sidemenu { position: fixed; top: 50px; left: 20px; background: #444; width: 120px; }
    #sidemenu ul { list-style-type: none; margin: 0; padding: 0; }
    #sidemenu li { margin: 5px; padding: 5px; width: 100px; text-align: center; }
    #sidemenu li.selected { background: #555; }
    #sidemenu a { text-decoration: none; color: #bbbbff; }
    #sidemenu a:hover { color: #fff; }
    • This CSS highly variable. Change the position, size and colors as desired.

  • Script
    $(document).ready(function(){
    $('#sidemenu').visualNav();
    });
Alternate Setup
  • HTML
    <div id="menu">
    <div class="link" title="#Home">Home</div>
    <div class="link" title="#work">Work</div>
    <div class="link" title="#blog">Blog</div>
    <div class="link" title="#projects">Projects</div>
    <div class="link" title=".about">About</div>
    <div class="link" title=".contact">Contact</div>
    </div>
    • This side menu uses divs with a title attribute. The value in this attribute can be used to target an Id or a class (which should be unique).
    • It is important to note, that this menu will not work with javascript disabled, whereas the default one will work.
  • CSS
    #menu { position: fixed; top: 50px; left: 20px; background: #444; width: 120px; }
    #menu div.link { margin: 5px; padding: 5px; width: 100px; text-align: center; }
    #menu div.selected { background: #555; }
  • Script
    $(document).ready(function(){
    $('#menu').visualNav({
    link              : 'div.link',
    targetAttr        : 'title',
    selectedAppliedTo : 'div.link'
    });
    });
Customizing / Options
This plugin has the following default options, so you will only need to include the line below in the script options if you want to change the default:
$('#sidemenu').visualNav({
link              : 'a',        // Add a link class, as necessary
targetAttr        : 'href',     // added in case you have link = "div" and attribute something like
selectedClass     : 'selected', // css class applied to menu
selectedAppliedTo : 'li',       // to only apply to the link, use "a"
topRange          : 100,        // measure from the top of the viewport to X pixels down
topMargin         : 100,        // margin above the top where the target updates the menu
bottomMargin      : 20,         // margin from the end of the page where the last menu item is used
animationTime     : 1200        // time in milliseconds
});
  • The first four options should were hopefully made clear in the examples above.
  • To modify how the menu acts, you will need to adjust the "topRange", "topMargin" and "bottomMargin" values. I made this picture to better understand what these values do for you.
  • topRange: The "topRange" is basically the area where target needs to be inside of in order for the menu to update. For example, the target (found in the link attribute) starts under the topRange. As it moves up and crosses into the topRange. The script then updates the side menu to show that the target area is in view (or inside the view port).
  • topMargin: The top edge margin (topMargin) is the area above the view port. The top edge margin is used while the page is being scrolled up - the target is above the view port and as you scroll up, the target moves down. When the target is inside the edge margin, the menu will update and point to that target.
  • bottomMargin: The bottom edge margin is the area below the view port. It is when the page is scrolled down (the contents are moving up). When the bottom of the page is inside the bottom edge margin, the menu will update with the last targeted id. This was necessary to be include in case the last section is too short and unable to reach the top range area.
  • animationTime: The animation time is the time in milliseconds that the menu will scroll to the selected section.
Known Problems / Bugs / Suggestions
  • The menu will not select (or highlight) the item above the last item if they are both very short. For example, if your browser shows three sections while at the bottom of the page. The third to last may have shown for a brief time just before the bottom of the page reached the bottom edge margin. The menu would then skip directly to the last menu item. This is one reason why the bottom margin value is kept a low number (20 pixels by default).
  • If you click on a menu item, the page contents will automatically scroll to that section and update the browser url with that target. But if you manually scroll the page using the scroll bar or mouse, the web page url will not update with the current position. This was done on purpose, because if the script changes the location, the page will jump to that target automatically. This wouldn't look good if you are quickly scrolling through the page as it would make the movement jittery.
  • To make suggestions or report any bugs please email me at wowmotty at g mail dot com.