1

I have a <header> that in turn contains two divs, as shown in the following image:

Fig 07 In the upper half the div A and in the lower half the div B. Well, what I want to do is a sticky menu, that when the upper part of the lower div (red) is zero then the whole header has a fixed position, hiding the upper div (blue) with the browser window. That is: Fig 07-02 This is my code:

    $(document).ready(function(){
    
        let smenu = $('.divB');
        stickyMenu(smenu);
    
        function stickyMenu(menu){
            $(window).on('scroll', function(){
                if($(this).scrollTop() > menu.offset().top) menu.addClass('menu-fixed');
                else menu.removeClass('menu-fixed');
            });
        }
    });
    body {
        height: 8000px;
    }
    
    header{
        background-color: transparent;
        width: 95%;
        margin: auto;
        overflow: hidden;
        transform: translateY(20px);
    }
    
    header .divA{
        width: 100%;
        background-color: #FFF;
        z-index: 1;
        overflow: hidden;
        border-top-left-radius: 5px;
        border-top-right-radius: 5px;
        height: 40px;
        width: 100%;
        background-color: red;
    }
    
    header .divB{
        width: 100%;
        background-color: #FFF;
        z-index: 1;
        overflow: hidden;
        border-bottom-left-radius: 5px;
        border-bottom-right-radius: 5px;
        height: 40px;
        width: 100%;
        background-color: green;
    }
    
    /*This class is to "stick" the menu on the top*/
    .menu-fixed{
        position: fixed;
        z-index: 999;
        width: 100%;
        top: 0;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
    <div class="divA">
        divA
    </div>
    <div class="divB">
        divB
    </div>
    </header>

The problem is that when doing scroll, the complete header leaves the window (upwards) and gets stuck there until I scroll down.

Web Nexus
  • 1,150
  • 9
  • 28
Héctor M.
  • 2,302
  • 4
  • 17
  • 35
  • Why not just set `top` equal to the height of `A`? – Obsidian Age Jan 29 '19 at 00:27
  • @ObsidianAge Because this code is an example, in the code of my project I have the upper div divided into parts and by doing this, the lower div is not displayed (I already thought of that) – Héctor M. Jan 29 '19 at 00:30

1 Answers1

1

You have number of issues with your css and javascript. First in CSS using position: fixed inside elements with transform property will take away the "fixed" behavior. Check this answer on Stackoverflow

In your JS you evaluate offset on every scroll event. This will lead to confusion as the class being applied to your divB "menu-fixed" changes offset().top and will cause scroll event to read a new top offset every time. So, as I have done in the code below, keep the top offset out of the scroll event. This will keep reference to the original top offset instead of updating every event which will cause undesired effect.

$(document).ready(function() {

  let smenu = $('.divB');
  stickyMenu(smenu);

  function stickyMenu(menu) {
  // Keep offset value out of scroll event
    var top = menu.offset().top;
    $(window).on('scroll', function() {
      var hasMoved = $(this).scrollTop() > top;
      (hasMoved == true) ? menu.addClass('menu-fixed'): menu.removeClass('menu-fixed');

    });
  }
});
body {
  height: 8000px;
}

header {
  background-color: transparent;
  width: 95%;
  margin: auto;
  /* Transform will act as a containing block for fixed position elemenets
   transform: translateY(20px);*/
 position: relative;
 top: 20px;
  overflow: hidden;
}

header .divA {
  width: 100%;
  background-color: #FFF;
  z-index: 1;
  overflow: hidden;
  border-top-left-radius: 5px;
  border-top-right-radius: 5px;
  height: 40px;
  width: 100%;
  background-color: red;
}

header .divB {
  width: 100%;
  background-color: #FFF;
  z-index: 1;
  overflow: hidden;
  border-bottom-left-radius: 5px;
  border-bottom-right-radius: 5px;
  height: 40px;
  width: 100%;
  background-color: green;
}


/*This class is to "stick" the menu on the top*/

.menu-fixed {
  position: fixed;
  z-index: 999;
  width: 100%;
  top: 0;
  left: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header>
  <div class="divA">
    divA
  </div>
  <div class="divB">
    divB
  </div>
</header>
Kalimah
  • 11,217
  • 11
  • 43
  • 80