Search code examples
javascriptjqueryhtmlfunctionscroll

How to Toggle Show/Hide a Fixed Element When Scrolling Through a Specific Div?


I am trying to figure out how to toggle between showing and hiding a fixed-positioned element when scrolling through a specific div.

Here is a diagram of what I would like to accomplish:

enter image description here

So far, I've been able to hide #div2 when another div (#div3) is visible within a window, (as shown in the snippet provided), but I would like for it to be hidden as well before it reaches the scroll top position of #div1.

Alternatively, I suppose a more ideal solution would be to just assign the div to toggle display only within the top and bottom scroll point parameters of #div1.

Any suggestions?

$(document).ready(function() {
  var $window = $(window);
  var div2 = $('#div2');
  var div1 = $('#div1');
  var div1_top = div1.offset().top;
  var div1_height = div1.height();
  var div1_bottom = div1_top + div1_height;
  console.log(div1_bottom);
  $window.on('scroll', function() {
    var scrollTop = $window.scrollTop();
    var viewport_height = $(window).height();
    var scrollTop_bottom = scrollTop + viewport_height;
    div2.toggleClass('hide', scrollTop_bottom > div1_bottom);
  });
});
body {
  background: #ccffcc;
  padding: 0;
  margin: 0;
  border: 0;
  text-align: center;
}

#div1 {
  background: #0099ff;
  height: 1500px;
  color: #fff;
}

#div2 {
  width: 100px;
  height: 100px;
  text-align: center;
  position: fixed;
  margin: auto;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  background: #ffff00;
  color: #000;
}

#div2.hide {
  display: none;
}

#div3 {
  height: 100px;
  color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<br>
<br>
<br>
<br>
<br>
Scroll area <b>before</b> arriving to the top of <b>div1</b>
<br>
<i>(Scrolling through this area <u>should not</u> display <b>div2</b>)</i>
<br>
<br>
<br>
<br>
<br>
<br>
<div id="div1">
  <div id="div2">This is <b>div2</b></div>
  This is <b>div1</b>
  <br>
  <i>(Toggle show/hide <b>div2</b> when scrolling past the top of this element)</i>
</div>
<div id="div3">
  This is <b>div3</b>
  <br>
  <i>(Toggle show/hide <b>div2</b> every time this div becomes visible in the window)</i>
</div>


Solution

  • I modified your scroll handler. You just need a second condition that adds the viewport height to the current scrollTop for the check at the bottom.

    Also, it worked better to use document.documentElement.scrollTop instead.

    Finally, I changed your .hide to .show and started #div2 out as display: none. Your toggle now uses this class.

    $(document).ready(function() {
      var $window = $(window);
      var div2 = $('#div2');
      var div1 = $('#div1');
      var div1_top = div1.offset().top;
      var div1_height = div1.height();
      var div1_bottom = div1_top + div1_height;
      console.log(div1_bottom);
      $window.on('scroll', function() {
        var scrollTop = document.documentElement.scrollTop;
        var viewport_height = $window.height();
        var scrollTop_bottom = scrollTop + viewport_height;
        div2.toggleClass('show', scrollTop > div1_top && (scrollTop + window.innerHeight) < div1_bottom);
      });
    });
    body {
      background: #ccffcc;
      padding: 0;
      margin: 0;
      border: 0;
      text-align: center;
    }
    
    #div1 {
      background: #0099ff;
      height: 1500px;
      color: #fff;
    }
    
    #div2 {
      width: 100px;
      height: 100px;
      text-align: center;
      position: fixed;
      margin: auto;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      background: #ffff00;
      color: #000;
    display: none;
    }
    
    #div2.show {
      display: block;
    }
    
    #div3 {
      height: 100px;
      color: #000;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <br>
    <br>
    <br>
    <br>
    <br>
    Scroll area <b>before</b> arriving to the top of <b>div1</b>
    <br>
    <i>(Scrolling through this area <u>should not</u> display <b>div2</b>)</i>
    <br>
    <br>
    <br>
    <br>
    <br>
    <br>
    <div id="div1">
      <div id="div2">This is <b>div2</b></div>
      This is <b>div1</b>
      <br>
      <i>(Toggle show/hide <b>div2</b> when scrolling past the top of this element)</i>
    </div>
    <div id="div3">
      This is <b>div3</b>
      <br>
      <i>(Toggle show/hide <b>div2</b> every time this div becomes visible in the window)</i>
    </div>