Make div stick to top of page after scrolling past another div?

I would recommend adding a class to #sticky when it's ready to be fixed to the top of the screen, and then removing that class when you want to 'unstick' it. Then you can manipulate that class in CSS.

e.g. for a class fixed you'd put the following in your CSS:

#sticky {
    display: none;
    background-color: #546bcb;
    height: 70px;
}
#sticky.fixed {
    display: block;
    position: fixed;
    top: 0;
    width: 100%;
}

And then your jQuery would look like this:

$(window).scroll(function() {
    var distanceFromTop = $(this).scrollTop();
    if (distanceFromTop >= $('#header').height()) {
        $('#sticky').addClass('fixed');
    } else {
        $('#sticky').removeClass('fixed');
    }
});

Here's an updated FIDDLE

I might also recommend some jQuery fade or slide effects (see the fiddle).


You can use position: fixed and in js detect when user scroll like this:

$(document).scroll(function() {
  //detect when user scroll to top and set position to relative else sets position to fixed
  $("#sticky").css({
    "top": "0",
    "position": $(this).scrollTop() > 140 ? "fixed" : "relative"
  });
});
body {
  margin: 0px;
  background-color: #e3e3e3;
}
#header {
  background-color: #cb5454;
  height: 140px;
}
#sticky {
  background-color: #546bcb;
  height: 70px;
  width: 100%;
  position: fixed;
}
#section {
  height: 1500px;
}
#footer {
  background-color: #cb5454;
  height: 140px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="header"></div>
<div id="sticky"></div>
<div id="section"></div>
<div id="footer"></div>

References

.scroll()


In my case, the div I wanted to be sticky was inside of another div (ie. not stuck to the page, but in another fixed div on the side of the page). Here's my adaptation of @bowhart's answer to solving this problem given a React component (sticky_adapter.js):

module.exports.makeItSticky = function(thisReactComponent, parentScrollNode = window) {
  const thisNode = $(ReactDOM.findDOMNode(thisReactComponent));
  const position = thisNode.position();

  // Uncomment for verbose logging
  //console.log("Initial position: " + UIUtils.stringify(position));

  const scrollContainer = $(parentScrollNode);
  scrollContainer.scroll(() => {
    const distanceFromTop = scrollContainer.scrollTop();
    // Uncomment for verbose logging
    //console.log("ScrollTop: " + distanceFromTop);

    if (distanceFromTop > position.top) {
      thisNode.addClass("stick-to-top");
    } else {
      thisNode.removeClass("stick-to-top");
    }
  });
};

Now, to make any React component sticky, I just add to the class:

componentDidMount() {
  StickyAdapter.makeItSticky(this, ".some-other-div-which-is-the-container");
}

Finally, the css for the sticky class:

.stick-to-top {
  display: block;
  position: sticky;
  top: 0;
  z-index: 10;
}