1

My aim is to have the menu bar stick at the top of the viewport once the header has been scrolled past.

I have used this jQuery to achieve this and have used the following code to modify the css when the menu bar reaches the top:

jQuery(document).ready(function($){
    // Check the initial Poistion of the Sticky Header
    var stickyHeaderTop = $('#stickyMenu').offset().top;

    $(window).scroll(function(){
            if( $(window).scrollTop() > stickyHeaderTop ) {
                    $('#stickyMenu').css({position: 'fixed', top: '0px'});
                    $('#stickyAlias').css('display', 'block');
                } else {
                    $('#stickyMenu').css({position: 'static', top: '0px'});
                    $('#stickyAlias').css('display', 'none');
            }
    });
});

Here is my dev page with my working example: http://dev.harryg.me/serge/home/

It works a dream in Firefox, but there is an issue with Chrome; the css change seems to kick in much earlier than it should - after only scrolling a few pixels down the menu bar becomes fixed and sticks to the top. I have a feeling the header image is to blame but cannot figure out why...

EDIT: Thank you for all your suggestions. As I am away from my dev setup I will have to wait to reveiw all your suggestions. As Explosion Pills and Malk was saying, the issue is because the stickyHeaderTop is calculated before the header image is loaded. This is why it works once the image is cached, but not if you refresh the page. I will try Explosion Pills' solution(s) later and upvote/accept as required.

harryg
  • 23,311
  • 45
  • 125
  • 198
  • try .position().top instead – Popnoodles Jan 31 '13 at 00:49
  • Your site is working fine for me in Chrome. Perhaps you already fixed it. – Malk Jan 31 '13 at 00:59
  • @Malk You sure? doesn't work *properly* for me in Chrome either – Madbreaks Jan 31 '13 at 01:00
  • Yes it is weird. It didn't at first, but I set a breakpoint in the scroll function just to watch values and it started working. I dumped the browsing history for the site and it is still working properly. – Malk Jan 31 '13 at 01:05
  • @harryg this is a long shot, but update your html so that the `#home_link img` has width/height, as in `Serge Dev` – Explosion Pills Jan 31 '13 at 01:07
  • I can replicate my experience. Clear browser data for the site: chrome://settings/clearBrowserData. Load the page. Notice the issue is present. Now scroll back to the top and refresh the page (by clicking the omnibox and press enter). The issue goes away for me. – Malk Jan 31 '13 at 01:13

3 Answers3

2

The issue is that the image at the top is not rendered and its height is not accounted for in the layout when you first calculate stickyHeaderTop. There are two solutions (both very simple):

  1. Add correct width and height attributes to the <img> at the top (inside <a id="home_link">). It's a good idea to do this anyway.
  2. Do not calculate stickyHeaderTop initially. Instead do the comparison $(window).scrollTop() > $("#stickyMenu").offset().top. The unnoticeable decrease in effiency is worth the accurate calculation.

You can do both too, if you want.

Explosion Pills
  • 188,624
  • 52
  • 326
  • 405
1

I've been dealed with chrome on same issue, it may be two possibilities to cause this bug:

  • Not using variable inside condition if( $(window).scrollTop() > stickyHeaderTop ) {

  • Try to change order of your css() functions like this:

    $('#stickyAlias').css('display', 'block');

    $('#stickyMenu').css({position: 'fixed', top: '0px'});

I've got problems beacuse of these 1 year ago while building this site.

If both don't work, give it try this way:

Here is working jsFiddle.

$(window).scroll(function() {

   var headerH = $('.header').outerHeight(true);
   console.log(headerH);
   //this will calculate header's full height, with borders, margins, paddings

   var scrollVal = $(this).scrollTop();
    if ( scrollVal > headerH ) {
        $('#subnav').css({'position':'fixed','top' :'0px'});
    } else {
        $('#subnav').css({'position':'static','top':'0px'});
    }
 });

Source.

Community
  • 1
  • 1
Barlas Apaydin
  • 7,233
  • 11
  • 55
  • 86
1

I think the document.ready event is firing before rendering is complete. Try subscribing to the load event of the window rather than the ready event of the document. Something like:

function scrollSpy(){
// Check the initial Poistion of the Sticky Header
    var stickyHeaderTop = $('#stickyMenu').offset().top;

    $(window).scroll(function(){
            if( $(window).scrollTop() > stickyHeaderTop ) {
                    $('#stickyMenu').css({position: 'fixed', top: '0px'});
                    $('#stickyAlias').css('display', 'block');
                } else {
                    $('#stickyMenu').css({position: 'static', top: '0px'});
                    $('#stickyAlias').css('display', 'none');
            }
    });
}
window.addEventListener('load', scrollSpy, false);
Malk
  • 11,855
  • 4
  • 33
  • 32