This is a (Javascript/CSS) Fixed menu.

JTricks.com;
Javascript Tricks, Samples, Tutorials & Howtos

New versions notifications available via

Follow jtricksdotcom on Twitter
/ JTricks.com / Navigation / Fixed & Sticky Menu
Last updated: 27 Nov 2007
Fixed & Sticky Menu
Many web pages don't fit on most users' screens. The visitors have to scroll to read the page contents. Such scrolling however hides the navigation menus usually located at the top of the page.

Newer browsers (such as Firefox or Internet Explorer 7) support position:fixed CSS option to pin something to particular window place. However page layout will be ruined if it is not supported by the browser. The javascript sample here will try to use position:fixed if available, falling back to moving DIV with position:absolute if fixed positioning isn't available. Most notable browser not to support position:fixed is Internet Explorer 6, which is still widely used when this article was written.

Absolute Floating Menu will provide floating menu with slow movement effect towards the desired spot.
Script demonstration
Look for the fixed menu box somewhere on the page.

Click the buttons to move the fixed menu to different corners:

Script source code
To use the script perform the following steps:

  • Create a DIV element with id of 'floatdiv' which contains the menu markup. Please note that it should have osition:absolute (which will be changes on the fly to position:fixed by through javascript if it is supported by the browser). Initial position should be specified via left, right, top, bottom CSS properties. For example:
<div id="fixeddiv" style="
    position:absolute;
    width:200px;height:50px;right:10px;top:10px;
    padding:16px;background:#FFFFFF;
    border:2px solid #2266AA">
This is a (Javascript/CSS) Fixed menu.
</div>
<script type="text/javascript"><!--
/* Script by: www.jtricks.com
 * Version: 20071127
 * Latest version:
 * www.jtricks.com/javascript/navigation/fixed_menu.html
 */
fixedMenuId = 'fixeddiv';

var fixedMenu = 
{
    hasInner: typeof(window.innerWidth) == 'number',
    hasElement: document.documentElement != null
       && document.documentElement.clientWidth,

    menu: document.getElementById
        ? document.getElementById(fixedMenuId)
        : document.all
          ? document.all[fixedMenuId]
          : document.layers[fixedMenuId]
};

fixedMenu.computeShifts = function()
{
    fixedMenu.shiftX = fixedMenu.hasInner
        ? pageXOffset
        : fixedMenu.hasElement
          ? document.documentElement.scrollLeft
          : document.body.scrollLeft;
    if (fixedMenu.targetLeft > 0)
        fixedMenu.shiftX += fixedMenu.targetLeft;
    else
    {
        fixedMenu.shiftX += 
            (fixedMenu.hasElement
              ? document.documentElement.clientWidth
              : fixedMenu.hasInner
                ? window.innerWidth - 20
                : document.body.clientWidth)
            - fixedMenu.targetRight
            - fixedMenu.menu.offsetWidth;
    }

    fixedMenu.shiftY = fixedMenu.hasInner
        ? pageYOffset
        : fixedMenu.hasElement
          ? document.documentElement.scrollTop
          : document.body.scrollTop;
    if (fixedMenu.targetTop > 0)
        fixedMenu.shiftY += fixedMenu.targetTop;
    else
    {
        fixedMenu.shiftY += 
            (fixedMenu.hasElement
            ? document.documentElement.clientHeight
            : fixedMenu.hasInner
              ? window.innerHeight - 20
              : document.body.clientHeight)
            - fixedMenu.targetBottom
            - fixedMenu.menu.offsetHeight;
    }
};

fixedMenu.moveMenu = function()
{
    fixedMenu.computeShifts();

    if (fixedMenu.currentX != fixedMenu.shiftX
        || fixedMenu.currentY != fixedMenu.shiftY)
    {
        fixedMenu.currentX = fixedMenu.shiftX;
        fixedMenu.currentY = fixedMenu.shiftY;

        if (document.layers)
        {
            fixedMenu.menu.left = fixedMenu.currentX;
            fixedMenu.menu.top = fixedMenu.currentY;
        }
        else
        {
            fixedMenu.menu.style.left = fixedMenu.currentX + 'px';
            fixedMenu.menu.style.top = fixedMenu.currentY + 'px';
        }
    }

    fixedMenu.menu.style.right = '';
    fixedMenu.menu.style.bottom = '';
};

fixedMenu.floatMenu = function()
{
    fixedMenu.moveMenu();
    setTimeout('fixedMenu.floatMenu()', 20);
};

// addEvent designed by Aaron Moore
fixedMenu.addEvent = function(element, listener, handler)
{
    if(typeof element[listener] != 'function' || 
       typeof element[listener + '_num'] == 'undefined')
    {
        element[listener + '_num'] = 0;
        if (typeof element[listener] == 'function')
        {
            element[listener + 0] = element[listener];
            element[listener + '_num']++;
        }
        element[listener] = function(e)
        {
            var r = true;
            e = (e) ? e : window.event;
            for(var i = 0; i < element[listener + '_num']; i++)
                if(element[listener + i](e) === false)
                    r = false;
            return r;
        }
    }

    //if handler is not already stored, assign it
    for(var i = 0; i < element[listener + '_num']; i++)
        if(element[listener + i] == handler)
            return;
    element[listener + element[listener + '_num']] = handler;
    element[listener + '_num']++;
};

fixedMenu.supportsFixed = function()
{
    var testDiv = document.createElement("div");
    testDiv.id = "testingPositionFixed";
    testDiv.style.position = "fixed";
    testDiv.style.top = "0px";
    testDiv.style.right = "0px";
    document.body.appendChild(testDiv);
    var offset = 1;
    if (typeof testDiv.offsetTop == "number"
        && testDiv.offsetTop != null 
        && testDiv.offsetTop != "undefined")
    {
        offset = parseInt(testDiv.offsetTop);
    }
    if (offset == 0)
    {
        return true;
    }

    return false;
};

fixedMenu.init = function()
{
    if (fixedMenu.supportsFixed())
        fixedMenu.menu.style.position = "fixed";
    else
    {
        var ob = 
            document.layers 
            ? fixedMenu.menu 
            : fixedMenu.menu.style;

        fixedMenu.targetLeft = parseInt(ob.left);
        fixedMenu.targetTop = parseInt(ob.top);
        fixedMenu.targetRight = parseInt(ob.right);
        fixedMenu.targetBottom = parseInt(ob.bottom);

        if (document.layers)
        {
            menu.left = 0;
            menu.top = 0;
        }
        fixedMenu.addEvent(window, 'onscroll', fixedMenu.moveMenu);
        fixedMenu.floatMenu();
    }
};

fixedMenu.addEvent(window, 'onload', fixedMenu.init);

//--></script>
  • Be sure to verify page design with the Javascript turned off.
Browser compatibility
The javascript snippet above was tested on the following user agents:

Mozilla/Netscape Firefox 2.0.x Ok *.
Firefox 1.5 Ok *.
Firefox 1.0.x Ok *.
Netscape Navigator 4.79 Downgrades gracefully ***.
Microsoft Internet Explorer 7.0 Ok *.
Internet Explorer 6.0 Jumpy **.
Internet Explorer 5.0 Jumpy **.
Opera Opera 9.x Ok *.
Opera 8.x Ok *.
KHTML Konqueror 3.5.5 Ok *.
No Javascript or
Javascript turned off
Any Downgrades gracefully *.

*: Ok means the browser supports position:fixed and the best visual effect is achieved.
**: Jumpy means the browser doesn't support position:fixed and a DIV with position:absolute is repositioned when the page is scrolled.
***: Graceful degradation means the box is shown in its initial place with position:absolute and is not moved.
Donations and Script Rating
If you like our script, please
or at least rate it @ hotscripts.com!