0

I have a drop down menu that sits inside a header that is set to position: fixed. When viewed on a mobile device, I want the header to remain fixed, but when the menu is activated, jQuery dynamically changes the header's position to relative. That works fine (see code below), but there are a few problems that I need to fix. If the menu-toggle link is clicked again (closing the menu), the header does not return to its previous state "relative". Is there a way to do this? I also notice a flicker, so let's say you scroll half way down the page, then click on the menu to open it, the page sort of jumps and does not scroll back to the top where the menu is located inside the header as it should. I would prefer a pure CSS solution, but that seems impossible. I COULD set the rules so that if it's less than 499 pixels wide, the header gets positions "relative", but then usability fails, as a user will have to scroll up to the top of the page to access the drop down menu.

Any help would be greatly appreciated.

Here is my code:

HTML

<header role="banner" class="secondary">
<a href="#menu" class="menu-toggle"><em>Menu</em> <span aria-hidden="true"></span></a>
<nav id="nav" role="navigation">
<ul class="menu set">
<li class="subnav">
<a href="#">Link</a>
    <ul class="sub-menu">
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
        <li><a href="#">Link</a></li>
    </ul>
</li>
</ul>
</nav>
</header>

CSS

header[role="banner"] {
    width: 100%;
    background: #fff;
    display: block;
    margin: 0 auto;
    padding: 0;
    box-shadow: 0 2px 4px rgba(0,0,0,0.25);
    z-index: 10000; 
}

@media all and (min-width: 500px) {
    header[role="banner"] {
        position: fixed;
        top: 0;
        left: 0;
        clear: both;
        height: auto;
        display: block;
    }
}

@media all and (max-width: 499px) {
    header[role="banner"] {
        position: fixed;
    }
}

JAVASCRIPT

$(document).ready(function() {

    $('body').addClass('js');
          var $menu = $('#nav'),
              $menulink = $('.menu-toggle'),
              $menuTrigger = $('.subnav > a');

    $menulink.click(function(e) {
            e.preventDefault();
            $menulink.toggleClass('active');
            $menu.toggleClass('active');
    });

    var add_toggle_links = function() {         
        if ($('.menu-toggle').is(":visible")){
            if ($(".toggle-link").length > 0){
            }
            else{
                $('.subnav > a').before('<span class="toggle-link">Open</span>');
                $('.toggle-link').click(function(e) {       
                    var $this = $(this);
                    $this.toggleClass('active').siblings('ul').toggleClass('active');
                }); 
            }
        }
        else{
            $('.toggle-link').empty();
        }
     }
    add_toggle_links();
    $(window).bind("resize", add_toggle_links); 

        });


        $(document).ready(function() {
            $('.menu-toggle').click(function() {
               if ($( document ).width() < 499)
                  $('header[role="banner"]').css('position', 'relative');
            });
        });
JimiDini
  • 2,039
  • 12
  • 19
user2485157
  • 43
  • 1
  • 10

1 Answers1

0

So you don't actually have any js code in there that will switch the position of your header between fixed and relative.

What I would do is maybe toggleClass on your header.

$(document).ready(function() {
  $('.menu-toggle').click(function() {
    if ($( document ).width() < 499){
      $('header[role="banner"]').toggleClass('active');
    }
  });
});

Then in your css

header[role="banner"] {
  position: fixed;
}
header[role="banner"].active {
  position: relative;
}

The screen jump you're getting is probably from changing the position from fixed to relative, because relative will add the header back to the normal page flow. So to fix this, you could also toggle the class of whatever is below your header, so when active, it has a margin-top of 0, and when inactive, it has a margin-top equal to the height of the header.

n_i_c_k
  • 1,504
  • 10
  • 18
  • Hi Nick. Thank you for your help. The toggle code you provided works perfectly, but I am still getting that jump. So if I scroll to the middle of the page when less than 499 pixels wide, and then click on the menu to open (drop down on mobile), the page jumps up only a small amount (maybe like 150 px) from the point i was at when i clicked to open the menu. I added another toggle rule in the javascript as you suggested but it didn't work. Perhaps I am doing it wrong? – user2485157 Sep 30 '13 at 20:18
  • I think the problem is when you are half way down the page and you decide to open the menu, and it drops down, because the toggled class is set to relative in the header's position, the menu is not sticking to the top. I have no idea how to fix this. – user2485157 Sep 30 '13 at 21:11
  • Well, if you scroll way down the page, and then change your header's position from `fixed` to `relative`, the header will of course jump in the layout to it's normal flow position. That's why I thought you maybe wanted the page to scroll to the top when someone hits the menu-toggle – n_i_c_k Oct 01 '13 at 00:03
  • Good point. How would I set it so when a user hits the menu it scrolls to the top? – user2485157 Oct 01 '13 at 04:09
  • Question answered here: http://stackoverflow.com/questions/4034659/is-it-possible-to-animate-scrolltop-with-jquery If you're satisfied with my answer, will you mark it as correct plz? – n_i_c_k Oct 01 '13 at 17:55
  • Hi Nick. I checked the check mark as correct. Thank you for your help! :) – user2485157 Oct 02 '13 at 18:24