Unstick a fixed element based on page scroll

I have a calculator on my site (written in php), and in the end of this calculator there is a div with the results.

On desktop it works fine, but on mobile, i want to fix the results div to the bottom until scrolling the original position of the div. After that i want to change its position to static.

In other words, there is a fixed (to bottom) element on the page and after scrolling, at the original position of the div, i want to unstick it.

I hope, its understandable, but there is an example page - Look at the MOBILE version!!!

How can i do that?

Thanks in advance!

2 answers

  • answered 2018-01-19 17:04 RyanDay

    Here's how I've done it in the past:

    1. Get the original position of the bottom of the element.
    2. Get the height of the viewport.
    3. Subtract the viewport height from the original bottom position to get where the window needs to be scrolled to in order for the full element to be in view.
    4. Add a scroll listener to the window to check the scroll position and add/remove the fixed class accordingly.

    Example:

    // Get the document element to use later.
    var doc = document.documentElement;
    
    // Get your important message.
    var importantMsg = document.getElementById('important-msg');
    
    // Find out how far the bottom of our message is from the top of the page while it's not fixed.
    var originalMsgBottom = importantMsg.getBoundingClientRect().bottom;
    
    // Get the window height.
    var windowHeight = Math.max(doc.clientHeight, window.innerHeight || 0);
    
    // Get the scroll position we need to check for while srolling.
    var scrollPosition = originalMsgBottom - windowHeight;
    
    // Now make your message fixed by default.
    importantMsg.className = 'important-msg-fixed';
    
    // Create the function to get the current scroll and see if it is greater than or equal to the position we defined earlier.
    var scrollFunction = function() {
    	var scrollTop = (window.pageYOffset || doc.scrollTop)  - (doc.clientTop || 0);
      if (scrollTop >= scrollPosition) {
        importantMsg.className = ''; // If it is, remove the fixed class.
      } else {
        importantMsg.className = 'important-msg-fixed'; // If it's not, then add it.
      }
    }
    
    // Make our function run everytime the window is scrolled.
    window.addEventListener('scroll', scrollFunction);
    #important-msg {
      background: #f00;
      color: #fff;
      padding: 10px;
    }
    .important-msg-fixed {
      position: fixed;
      right: 0;
      bottom: 0;
      left: 0;
      margin: 0;
    }
    <h1>Lorem Ipsum</h1>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p>Scroll Down</p>
    <p id="important-msg">Important Message</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>
    <p>More Stuff</p>

  • answered 2018-01-19 17:04 Roko C. Buljan

    If you don't care about IE browsers (or if you're reading this in 2022 :D)
    you can use position: sticky

    .sticky{
      position: sticky;
      bottom: 0;
      background: red;
    }
    <div class="content">
      <p style="border:4px dashed;height:150vh;">Scroll down</p>
      <div class="sticky">I'M STICKY</div>
    </div>
    
    <div class="content">
      <p style="border:4px dashed;height:150vh;">Scroll up</p>
    </div>

    https://caniuse.com/#feat=css-sticky

    If you want a (kind-of?) fallback you could:

    .sticky{
      position: absolute; /* fallback to absolute */
      width: 100%;        /* fallback width */
      position: sticky;
      bottom: 0;
      background: red;
    }