Published Jul 29. 2016 - 4 weeks ago

The fixed top menu

A lot of sites feature a part of the page – typically a top menu – that is fixed to the top of the screen when you scroll down. Here are some thoughts about such a feature and how to do it.

This is NOT about fly fishing or fly tying, but about site development and nerdy stuff
Fixed headers block a lot of content on these two pages
Martin Joergensen

I generally dislike fixed elements on a screen – for several reasons:
- They fill the screen space with permanent elements that I generally don't need.
- It breaks the user's feeling of seeing one page and having a “physical” sense of the position of things.
- The way some developers add dynamic transitions like zooms, swoops, fades and whatnot, doesn't appeal much to me. And it's often done technically clumsily, which also bothers me.
- It often comes with fairly complex code, sometimes even two copies of the same element – the dynamic and the fixed.

Screen estate

The first issue is my main argument against using fixed top bars or headers. A lot of sites simply set the header region of the page to be fixed and let the rest scroll. On my medium resolution laptop, that means that up to a third or more of the screen height is taken by static elements, leaving me way too little space to read and especially to see images.
From the top of the screen I may see the browser top bar and menu, the browser tabs, the browser's location entry field, my personal toolbox icons (like Firebug in Firefox) and then the fixed part of the page.
Sometimes I can add a fixed bottom on the page to that, like social media links, newsletter signup or some other footer content plus whatever the browser decides to put there and my Windows task bar. All that leaves preciously little space in the middle for actual page content.

High or low

The technical side of fixed content can be pretty simple. Just add the CSS style position:fixed to any element, and it stays where it was first rendered.
The most recent incarnation of Google Analytics uses this approach. It renders a page top, fixes it and simply leaves it there, scrolling the rest of the page under it. Many sites use this approach which is simple, but also the one that potentially uses up most space, because the header can often contain a lot of stuff like a logo, links, a menu, a search form and much more.
Other sites render the page with a normal header with all these elements, but once the user scrolls this header off the page, a smaller subset of the header fixes itself to the top of the page. Typically what remains is just a single line menu or a simplified header, and that takes up way less space than the full header.

Double up

Unfortunately this approach is mostly done by simply adding an extra element to the page. The fixed menu is rendered as one entity and the usual header as another – mostly these two contain something, which is close to identical or completely identical. Having these two elements allows the system to change the visibility of the fixed one when the normal header scrolls off screen.
But if the menu is large – like the menu on this site – containing many submenus, images, lists and much more, the user gets two almost identical copies adding load time and complexity.

Same, same but different

The solution to this is of course to have one menu only and fixing that as the user scrolls. This means that there's only one copy of the possibly complex and large menu, and, as it's the the case on this site, it also reliefs the developer from having to juggle identical id's and much more.
Luckily all the menu HTML for the Global FlyFisher is contained in a single element – a div with the id menubar. This is simply rendered as part of the header like it would be on any site and is positioned just beneath the top header of the page with the logo, search form and other elements. In order to fix it at the right time, we need to look at some element that scrolls on and off the page as the user moves down through the content. We can't look at the menu bar itself, since it will scroll off, but then be fixed onscreen. Again we're lucky, because almost on the same level as the menu bar, there's a search form, which rolls off screen as the user scrolls.

JavaSccript and CSS

Using jQuery to check the visibility of this form, we can change the class of the menu bar to something else – like fixed.
This is the script that does it:

(function($) { $(window).scroll(function(){
    var itemOffset = $('#block-search-form').offset().top;
    var scrollTop = $(window).scrollTop();
    if (scrollTop >= itemOffset) {
      $('#menubar').addClass("fixed");
    }
    else {
      $('#menubar').removeClass();
    }
});}(jQuery));
Global FlyFisher
Martin Joergensen

This is loaded into the html.tpl.php file, meaning that it will be loaded on all pages.
So normally the menu bar has no class, but when the search form moves off screen, it gets the class fixed.
In the CSS, .fixed has the property position:fixed, top:0 and a high z-index, which will staple it to the top edge of the screen and make sure it's visible. In the case of this site the rounded corners are also changed, the height is adjusted slightly and it's given a small shadow to add a 3D kind of effect.

The result

The result is a menu bar containing code for a large and complex menu, which appears only once on the page and is fixed using a very simple script and CSS. No major DOM changes are made, only a class is added or removed. And it's only done when the condition is triggered, which is just once or a few times as the user scrolls up and down on a page.
The downturn is the jQuery scroll() function, which is called all the time and which will potentially call our little function thousands of times during a normal page visit.
But I haven't experienced any performance problems with this solution, which works fine in all browsers and has been running flawlessly for years now.

Add new comment

Log in or register to pre-fill name on comments, add videos, user pictures and more.
Read more about why you should register.