简体   繁体   中英

Can I add a wrapper to my layout that has a pure CSS dynamic sticky footer?

After countless hours trying to find a way to implement a sticky footer with fluid height without resorting to using javascript, I finally found a way. No matter how much content I add to the .footer , it remains stuck to the bottom of the viewport, regardless of whether there is enough in the .content div to push it down. None of the javascript solutions I tried worked as smoothly as this, and I'd like to keep using this method if possible.

My problem is that due to an issue with various mobile browsers not accepting the overflow-x:hidden; rule on the body tag, I'm now having to add a wrapper to my layout. This fixes the mobile browser issue, but unfortunately stops the .footer from sticking to the bottom of the viewport when the .content div is empty.

I have of course tried to move several of the CSS rules from the body to the wrapper to see if this works, but I haven't had any success. Is there a way around this?

Here are two jsFiddle examples to show the problem, one with a .wrapper and one without.

Example 1: Without wrapper (Sticky footer works)https://jsfiddle.net/v5h2f5wd/

Example 2: With wrapper (Sticky footer does not work)https://jsfiddle.net/v5h2f5wd/1/

Code from Example 2:

<div class="wrapper">
    <header class="header"></header>
        <div class="content">
            <button>Click here to insert content into footer.</button>
        </div>
    <footer class="footer"></footer>
</div>

html {
    position:relative; 
    height:100%;
}

body {
    position:relative;
    width:100%;
    min-height:100%;
    margin:0; 
    padding:0; 
    overflow-x:hidden;
    background-color:#eee;
    display:-webkit-box;
    display:-webkit-flex;
    display:-ms-flexbox;
    display:flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -webkit-flex-direction: column;
    -ms-flex-direction: column;
    flex-direction: column;
}

.header {
    position:absolute;
    width:100%;
    height:55px;
    background-color:#fff;
}

.content {
    -webkit-box-flex:1;
    -webkit-flex:1;
    -ms-flex:1;
    flex:1;
    width:100%;
    height:auto;
    background-color:pink;
}

button { 
    margin:65px 0 0 10px;
} 

.footer {
    width:100%; 
    background-color:#fff;
    padding:25px 0;
}

This is pretty simple with flexbox. No need for positioning at all.

 * { margin: 0; padding: 0; } html { height: 100%; } body { min-height: 100%; display: flex; flex-direction: column; } .wrapper { flex: 1; display: flex; flex-direction: column; } header { background: pink; } footer { background: red; padding: 1em; } main { flex: 1; background: lightgreen; } 
 <div class="wrapper"> <header>HEADER</header> <main> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Similique facere consequatur officiis cupiditate sed blanditiis magni sequi ducimus cum illum repellat ab nostrum excepturi aperiam dolor repudiandae mollitia, eius deleniti.</p> </main> <footer>FOOTER</footer> </div 

Here is a flexbox solution.

Looks like you were trying to do something similar. The key points in this setup are height: 100%; on the html element (inherits from viewport height), min-height: 100%; on body element (inherits from html height) and flex-grow: 1; on main element (tells element to take up remaining space inside the container element).

With this solution the footer's height is dynamic which saves you the headache of have to update selectors in your stylesheet if it ever changes.

The JS in the solution is simply for demo purposes.

 var btnC = document.querySelector( '.btn-c' ); var btnF = document.querySelector( '.btn-f' ); var main = document.querySelector( 'main' ); var footer = document.querySelector( 'footer' ); function addContent( target, str ) { var p = document.createElement( 'p' ); p.innerHTML = str; target.appendChild( p ); } btnC.addEventListener( 'click', function ( e ) { for ( var i = 0, len = 5; i < len; i++ ) { addContent( main, 'Content' ); } } ); btnF.addEventListener( 'click', function ( e ) { addContent( footer, 'Footer' ); } ); 
 html, body { height: 100%; } body { margin: 0; } header { background-color: gold; } main { flex-grow: 1; background-color: skyblue; } footer { background-color: indianred; } .wrap { display: flex; flex-direction: column; min-height: 100%; } 
 <div class="wrap"> <header> Header </header> <main> <p> Content </p> <button class="btn-c">Add to Content</button> <br> <button class="btn-f">Add to Footer</button> </main> <footer> Footer </footer> </div> 

No need to do all the positioning (unnecessary) and width declarations (those elements already take up 100% width because they're block level elements).

So all I did was slightly alter the CSS you had in your JSFiddle, and the reason why what you had didn't work was that you needed to apply the same structuring styles to the parent containers since they need to be the same.

To get the footer to stick to the bottom I just used the align-self flex property to position it at the end of the parent flex element.

Hopefully this will work for you.

html {
  position:relative; 
  height:100%;
}
body, 
.wrapper{
  height: 100%; /* this makes sure that the body matches the window and the wrapper matches the body. */
  display:-webkit-box;
  display:-webkit-flex;
  display:-ms-flexbox;
  display:flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column
}
body {
  position:relative;
  margin:0; 
  padding:0; 
  overflow-x:hidden;
  background-color:#eee;
}

.header {
  position:absolute;
  width:100%;
  height:55px;
  background-color:#fff;
}

.content {
  -webkit-box-flex:1;
  -webkit-flex:1;
  -ms-flex:1;
  flex:1;
  width:100%;
  height:auto;
  background-color:pink;
}

button { 
  margin:65px 0 0 10px;
}

.footer {
  width: 100%;
  -webkit-align-self: flex-end;
  -ms-flex-item-align: end;
  align-self: flex-end; /* This puts it at the end of the parent flex element. */
  background-color:#fff;
  padding:25px 0;
}

If you want to use it with your wrapper, maybe this would work for you.

 $(document).ready(function(){ $("button").click(function(){ $(".footer").append("Some text to make me taller."); }); }); 
 html { position:relative; height:100%; height: 100%; margin: 0px; padding: 0px; } body { position:relative; height: 100%; margin: 0px; padding: 0px; width:100%; min-height:100%; margin:0; padding:0; overflow-x:hidden; background-color:#eee; display:-webkit-box; display:-webkit-flex; display:-ms-flexbox; display:flex; -webkit-box-orient: vertical; -webkit-box-direction: normal; -webkit-flex-direction: column; -ms-flex-direction: column; flex-direction: column; margin:0; padding:0; height:100%; } .wrapper { height: 100%; } .header { position:absolute; width:100%; height:55px; background-color:#fff; } .content { -webkit-box-flex:1; -webkit-flex:1; -ms-flex:1; flex:1; width:100%; height:auto; background-color:pink; height: 100%; } button { margin:65px 0 0 10px; } .footer { width:100%; background-color:#fff; padding:25px 0; bottom: 0; position:absolute; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script> <div class="wrapper"> <header class="header"></header> <div class="content"> <button>Click here to insert content into footer.</button> </div> <footer class="footer"></footer> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM