Search code examples
htmlcssinternet-explorer-11sticky

make a div sticky in IE and in top of footer


I want to make a div sticky to scrolling, but when it will always stay at the top of the footer.

I tried using position:sticky which works fine, but it doesn't work on IE11.

I also tried multiple solutions for similar issue but they always referring on how to make the footer sticky and not another <div> inside the main <div>.

This is how my code looks:

.slider {
  background: #006264;
  color: white;
  position: sticky;
  bottom: 0px;
  width: 100%;
  height: 60px;
}

.footer {
  background: #04246A;
  color: white;
  font-weight: bold;
  margin: 0 auto;
  height: 119px;
}
<div class="main">
  <div class="placeholder">This div holds place</div>
  <div class="placeholder">This div holds place</div>
  <div class="placeholder">This div holds place</div>
  <div class="placeholder">This div holds place</div>
  <div class="placeholder">This div holds place</div>
  <div class="slider">
    This is the footer
  </div>
</div>
<div class="footer">This is the main footer</div>

Here it is on JSFiddle

How can I solve this?


Solution

  • Writing some few lines of JavaScript should do the trick for this requirement. We can have the main footer as our indicator if we should have the sub footer position: fixed or position: relative based on the current window scroll position - this is what sticky is after all, i.e., a hybrid of fixed & relative.

    In my solution below, the general advantage is that the event listener for scroll only kicks in when the client is using IE11. I've found that IE11 actually removes the sticky position style on the DOM since it does not support it.

    In short, moderns browsers are still going to use sticky and the below code is simply backup when the user is on IE11.

    <!-- place the style inline to cater the condition statement -->
    <div class="slider" style="position: sticky;">
    
    .slider {
      background: #006264;
      color: white;
      position: fixed; /* fixed is for the IE11 fallback */
      bottom: 0px;
      width: 100%;
      height: 60px;
    }
    
    // IE11 actually removes "sticky" from attribute "styles" value. So at this point we can control when to add an event listener (i.e., Modern browsers will still use position: sticky)
    if (divFooter.style.position != "sticky") {
      window.addEventListener("scroll", function() {
        if (mainFooter.getBoundingClientRect().top - window.innerHeight <= 0) {
          divFooter.style.position = "relative";
          mainFooter.style.marginTop = "0";
        } else if (mainFooter.getBoundingClientRect().top - window.innerHeight > 0) {
          divFooter.style.position = "fixed";
          mainFooter.style.marginTop = divFooter.clientHeight.toString() + "px";
        }
      })
    }
    

    var divFooter = document.querySelector(".slider");
    var mainFooter = document.querySelector(".footer");
    
    // IE11 actually removes "sticky" from attribute "styles" value. So at this point we can control when to add an event listener (i.e., Modern browsers will still use position: sticky)
    if (divFooter.style.position != "sticky") {
      window.addEventListener("scroll", function() {
        if (mainFooter.getBoundingClientRect().top - window.innerHeight <= 0) {
          divFooter.style.position = "relative";
          mainFooter.style.marginTop = "0";
        } else if (mainFooter.getBoundingClientRect().top - window.innerHeight > 0) {
          divFooter.style.position = "fixed";
          mainFooter.style.marginTop = divFooter.clientHeight.toString() + "px";
        }
      })
    }
    html,
    body {
      margin: 0;
    }
    
    .placeholder {
      border: 1px solid black;
      margin: 0 auto;
      text-align: center;
      height: 300px;
    }
    
    .slider {
      background: #006264;
      color: white;
      position: fixed;
      bottom: 0px;
      width: 100%;
      height: 60px;
    }
    
    .footer {
      background: #04246A;
      color: white;
      font-weight: bold;
      margin: 0 auto;
      height: 119px;
    }
    <div class="main">
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="slider" style="position: sticky;">
        This is the footer
      </div>
    </div>
    <div class="footer">This is the main footer</div>


    As far as a pure CSS solution - here is what I've got: you can opt to have 2 scrollbars. 1 for the body & 1 for main - we can hide the horizontal scrollbar for aesthetics.

    body {
      overflow-x: hidden;
    }
    
    .main {
      max-height: calc(100vh - 60px);
      overflow-y: scroll;
      width: 100vw;
    }
    

    html,
    body {
      margin: 0;
    }
    
    .placeholder {
      border: 1px solid black;
      margin: 0 auto;
      text-align: center;
      height: 300px;
    }
    
    .slider {
      background: #006264;
      color: white;
      /* position: sticky; */
      bottom: 0px;
      width: 100%;
      height: 60px;
    }
    
    .footer {
      background: #04246A;
      color: white;
      font-weight: bold;
      margin: 0 auto;
      height: 119px;
    }
    
    body {
      overflow-x: hidden;
    }
    
    .main {
      max-height: calc(100vh - 60px);
      overflow-y: scroll;
      overflow-x: hidden;
      width: 100vw;
    }
    <div class="main">
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
    </div>
    <div class="slider">
      This is the footer
    </div>
    <div class="footer">This is the main footer</div>

    Below you can find the inner workings of the CSS implementation minus the hiding of the scrollbar. This is pretty hacky - if you can find a way for the scrolling to prioritize the body on-scroll-up, that will do best for your system.

    html,
    body {
      margin: 0;
    }
    
    .placeholder {
      border: 1px solid black;
      margin: 0 auto;
      text-align: center;
      height: 300px;
    }
    
    .slider {
      background: #006264;
      color: white;
      /* position: sticky; */
      bottom: 0px;
      width: 100%;
      height: 60px;
    }
    
    .footer {
      background: #04246A;
      color: white;
      font-weight: bold;
      margin: 0 auto;
      height: 119px;
    }
    
    body {
      /* overflow-x: hidden; */
    }
    
    .main {
      max-height: calc(100vh - 60px);
      overflow-y: scroll;
      /* width: 100vw; */
    }
    <div class="main">
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
      <div class="placeholder">This div holds place</div>
    </div>
    <div class="slider">
      This is the footer
    </div>
    <div class="footer">This is the main footer</div>