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

30,985

Solution 1

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).

Solution 2

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()

Solution 3

Hey this is and old question but for new visitors I think u just need to add this css code to #sticky:

#sticky { position:sticky;top:0; }

and no need for javascript.

sticky toggles between relative and fixed, depending on the scroll position.

and don't forget that, the parent also should not have overflow property

Solution 4

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;
}
Share:
30,985
John
Author by

John

Updated on July 09, 2022

Comments

  • John
    John almost 2 years
    <div id="header"></div>
    <div id="sticky"></div>
    <div id="section"></div>
    <div id="footer"></div>
    
    <style>
      body { margin: 0px; background-color: #e3e3e3; }
      #header { background-color: #cb5454; height: 140px; }
      #sticky { background-color: #546bcb; height: 70px; }
      #section { height: 1500px; }
      #footer { background-color: #cb5454; height: 140px; }
    </style>
    

    Here is my code: http://jsfiddle.net/uaqh018d/

    I want #sticky to stick to the top of the page after scrolling past #header. I also want it hidden until stuck. And then of course have it unstick+hide again after scrolling back up to #header.

    How can I achieve this?

  • John
    John over 9 years
    ALMOST. WE'RE SO CLOSE. I just need to have it unstick when you scroll back up to bottom of #header, not when you scroll up to the very top of page.
  • John
    John over 9 years
    Oh, there we go! Your fiddle is working as it should now. Thanks man! I had to accept bowheart's answer. It appears to be more efficient, but thanks again!
  • John
    John over 9 years
    Thank you! I believe this to be more efficient!
  • SearchForKnowledge
    SearchForKnowledge over 9 years
    What is the height is dynamic and not known?
  • bowheart
    bowheart over 9 years
    @SearchForKnowledge You mean the height of the sticky header? jsfiddle.net/uaqh018d/40
  • Si8
    Si8 over 8 years
    I keep getting this error: Uncaught TypeError: Cannot read property 'scroll' of null
  • Saghachi
    Saghachi over 3 years
    the fade option in fiddle link make the menu disappear when scrolling back to top