La barra de navegación es uno de esos elementos que los webmasters suelen poner siempre accesible para el usuario, pero si nuestra barra no está diseñada desde un principio en la parte superior de la página necesitamos desanclarla cuando el usuario haga scroll.

En este caso voy a usar jQuery dado que se necesita calcular la distancia de la barra de navegación al margen superior, algo muy engorroso en javascript plano:

$(function () {
    var topDistance = $('#nav').offset().top;
    
    $(window).scroll(function () {
        if ($(window).scrollTop() > topDistance) {
            $('#nav').css({'position':'fixed','top':'0'});;
        } else {
            $('#nav').css({'position':'static'});
        }
    });
});

Con este escueto código tendríamos una barra de navegación que se ancla a la parte superior de la página cuando se hace scroll, sin embargo hay un problema, y es que el navegador ya no toma en cuenta la altura (height) de nuestro elemento, por lo que se produce un salto en la barra de desplazamiento cada vez que la barra cambia de fixed a static y viceversa. Para solucionarlo podemos, simplemente, alterar los atributos margin o padding del elemento anterior/siguiente de nuestra página. En mi caso añado padding superior en el elemento siguiente a mi barra de navegación, de clase ‘contenido’:

$(function () { // equivalente a document.ready()
    var topDistance = $('#nav').offset().top;
    var elHeight = $('#nav').outerHeight(true); // 'height' no nos da la altura deseada
    
    $(window).scroll(function () {
        if ($(window).scrollTop() > topDistance) {
            $('#nav').css({'position':'fixed','top':'0'});
            $('.contenido').css('padding-top', elHeight);
        } else {
            $('#nav').css({'position':'static'});
            $('.contenido').css('padding-top', 0);
        }
    });
});

Si lo queréis ver funcionando, tenéis un ejemplo aquí http://jsfiddle.net/QTbZg/1/