Search code examples
jqueryhtmlcssresponsive-designsticky-footer

css - relative header and sticky footer, dynamic content, unknown height, all in a container with responsive width?


Am working on a relative header and sticky footer, with dynamically loaded content (sometimes an empty div (unknown height) hence height: 100vh;), all within a responsive container that adjusts to the width of the device (width: 100vw;) up to a max-width of 350px.

From there, some content loads dynamically above the header and should push down the header and the content, but should keep the sticky footer in place. The dynamic content, when it overflows, should scroll out below the header and above the footer because both are semi-transparent.

Have tried all sorts of combinations of (relative and absolute)..here's the closest one, for example: http://jsfiddle.net/9U2CU/5/.. but this combination guesses the percentage height of the dynamic content, and the content that appears is incorrectly formatted in scope and does not push down the dynamic-content because of the absolute positioning!?

What adjustments need to be made to the CSS to account for the specs?

HTML

<div id="view">

    <div id="appear" style="display:none;">Content that appears</div>

    <div id="header">Some Buttons</div>
    <div id="dynamic-content"></div>
    <div id="footer">Some Buttons</div>

</div>

CSS

#view {
  position: relative;
  height: 100%;
  width: 100vw;
  max-width: 350px;
  overflow-y: auto;
  height: 100vh;
  display: block;
  margin: 0 auto;
  background-color: #fff;
}
#header {
  position: relative;
  height: 44px;
  width: 100%;
  background-color: rgba(255, 255, 255, .5);
}
#dynamic-content {
  position: relative;
  height: 100%;
  width: 100%;
  background-color: #999;
}
#footer {
  position: absolute;
  bottom: 0;
  width: 100%;
  height: 36px;
  background-color: rgba(255, 255, 255, .5);
}

jQuery

$(document).on("click", "#header", function () {
    $('#appear').slideToggle();
});

Solution

  • jsBin demo

    HTML:

    <div id="view">
      <div id="appear"> Content that appears </div>
      <div id="header"> Header </div>
      <div id="content"> <h1>Content</h1> <p>Lorem ipsum...</p> </div>
      <div id="footer"> Footer </div>
    </div>
    

    CSS3:
    using calc() which currently has a very good xBrowser support: http://caniuse.com/#search=calc

    #view {
      overflow: hidden;           /* NO SCROLLBARS */
      margin: 0 auto;
      background-color: #000;
      color:#fff;
    
      width: 100vw;
      max-width: 350px;
      height: 100vh;
    }
    #appear{
      display:none;
    }
    #header,
    #footer {
      height: 44px;               /* note this */
      background-color: #555;
    }
    #content {
      overflow-y: scroll;         /* SCROLLBARS !!!*/
      height: calc(100% - 88px);  /* 44+44 = 88px */
    }
    

    and finally
    jQuery:

    $("#view").on("click", "#header", function () {
      var $appear = $('#appear');
      var io = this.io ^= 1; // Toggler
    
      $appear.show();               // Temporarily show
      var animH = $appear.height(); // Get height and
      if(io) $appear.hide();        // fast hide.
      $appear.slideToggle();        // Now do it with animation
    
      $('#content').animate({       // Animate content height
          height: (io?"-=":"+=")+animH
        },{
          step: function() {
            $(this).css("overflow-y", "scroll");
          },
          complete : function(){
            var h = 88 + (io?animH:0); // header+footer = 88px
            $(this).css({height: "calc(100% - "+ h +"px)"});
          }
       });
    });
    

    To explain the beauty above:
    the trick is to set a fixed height to header and to Footer, than using calc(100% - 88px) for the scrollable content you get the needed space.

    On jQuery animate you just quickly get the Appearing Top content height and apply it to the calc() magic in jQuery.