Mugo Web main content.

Fixed positioning of page elements while scrolling

By: Xavier Cousin | December 27, 2012 | User experience

We recently implemented two different designs where the menu remained fixed to the edge of the screen as the user scrolled. One case involved vertical scrolling and the other involved horizontal scrolling. Each had a subtle challenge and both were fun to work on!

The first use case was for a website redesign of New Zealand travel agency Frogs-in-NZ.

Frogs-in-NZ home

As you can see above, the layout is relatively standard, with a logo and tagline above the main menu. However, the Frogs-in-NZ team wanted to have the navigation bar stick to the top of the page as the user scrolls down the screen. The logo and tagline, though, should scroll out of view.

Frogs-in-NZ midpoint

The result of this is a smooth navigation experience that follows the user but goes back into its normal place when we scroll back to the top of the page. The simplest solution in this case is to adjust the "position" CSS property and switch it from "absolute" to "fixed" when the page has been scrolled beyond the original position of the navigation.

Using jQuery, here is how we accomplish the effect:

$(document).ready(function() {
    $(window).scroll(function() {
        navigation.scroll();
    });
});

var navigation = {
    settings : {
        offset: 127,
    },
    scroll : function() {
        var scroll_top = $(window).scrollTop(); // current vertical position from the top

        if( scroll_top > navigation.settings.offset ) {
            $('nav').css({ 'position': 'fixed', 'top': '0' });
        } else {
            $('nav').css({ 'position': 'absolute', 'top': navigation.settings.offset + 'px' });
        }
    }
};

The second use case was for a horizontal scroll feature for an interactive timeline:

TR Timeline

The left menu and overlay image scrolled with the user with the "position:fixed" CSS rule. However, we discovered an obscure bug in Safari where elements on a page would behave unexpectedly -- duplicating as the user scrolled -- when the page was accessed within an iframe and it contained fixed elements on top of embedded videos (yup, obscure and reproduced by many others!).

The solution in this case was similar to the first example, where we use absolute positioning while the page is scrolling, adjusting the pixel offset with JavaScript.

// On Safari on Mac, the presence of a Flash file in an iframe breaks position: fixed
// We force this for all Safari browsers; to limit this only to Mac browsers we can also add the check: navigator.userAgent.indexOf('Mac') > 0
// Therefore, we have to fake the fixed:position on scroll
if( navigator.userAgent.indexOf('Safari') > 0 )
{
    $('#kiosk-menu').css('position', 'absolute');
    $('.fixed-image').css('position', 'absolute');
    $(window).scroll( function(e)
    {
        var x = $(this).scrollLeft();
        var xFixedImage = x + 130;
        $('#kiosk-menu').css('left', x + 'px');
        $('.fixed-image').css('left', xFixedImage + 'px');
    });
}