Create a slide-out footer with this neat z-index trick

Demo Download

In this short tutorial, we are going to create an interesting slide-out footer with a bit of CSS. Grab the zip from the download button above, open it in your favorite code editor and read on!

The Idea

The effect we are after, is to give the impression that the page lifts up to reveal a footer, fixed in place. To achieve this:

  • The entire page content, apart from the footer, must reside in a single wrapping element (<div id="main"> in our case). This element will be given a z-index value of 1;
  • The footer must be set to a negative z-index value. It will provide the background color, and make room for the fixed part of the footer (the links and the colorful headings);
  • There must be an element that is set to a fixed positioning with relation to the bottom of the window, and it must have a z-index lower than the #main element, but higher than the footer.

You can learn more about the idea in the following illustration:

explained.jpg
The Footer Explained

Now let's see some code!

The HTML

Below you can see the markup of the page. This is basically a regular HTML5 document, in the <head> of which I include a font from Google Webfonts, and the HTML5 shim for older IE browsers.

index.html

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8"/>
        <title>Tutorial: A CSS3 slide-out footer</title>

        <link href="http://fonts.googleapis.com/css?family=PT+Sans+Narrow:700" rel="stylesheet" />

        <!-- The main CSS file -->
        <link href="assets/css/style.css" rel="stylesheet" />

        <!--[if lt IE 9]>
            <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>

    <body>

        <div id="main">

            <h1>A CSS3 slide-out footer.</h1>

        </div>

        <!-- The footer will go here -->

    </body>
</html>

The #main element wraps around the content of the page. As you will see in the next section, we will assign a positive z-index value to it, so that it is rendered above the footer. And here is the markup of the footer itself:

<footer>

    <ul>
        <li>
            <p class="home">Home</p>
            <a class="logo" href="#">Company Name <i>&copy; 2013</i></a>
        </li>
        <li>
            <p class="services">Services</p>

            <ul>
                <li><a href="#">3D modeling</a></li>
                <li><a href="#">Web development</a></li>
                <li><a href="#">Mobile development</a></li>
                <li><a href="#">Web &amp; Print Design</a></li>
            </ul>
        </li>
        <li>
            <p class="reachus">Reach us</p>

            <ul>
                <li><a href="#">Email</a></li>
                <li><a href="#">Twitter</a></li>
                <li><a href="#">Facebook</a></li>
                <li>555-123456789</li>
            </ul>
        </li>
        <li>
            <p class="clients">Clients</p>

            <ul>
                <li><a href="#">Login Area</a></li>
                <li><a href="#">Support Center</a></li>
                <li><a href="#">FAQ</a></li>
            </ul>
        </li>
    </ul>

</footer>

Inside the footer tag, we have an unordered list which holds four groups of links (defined using <li> elements). Each group has a paragraph, which is transformed into a colorful heading for the group, and another <ul> which holds the links. The outermost <ul> will be set to position:fixed, which will make it static with regard to the bottom of the browser window.

illustration.jpg
The Footer

The CSS

As you might guess, this is the place where things get interesting. In the beginning of the tutorial, I mentioned that we are going to work with negative z-indexes to make the footer fixed to the bottom of the screen. There is a very good article that explains z-indexes in detail, which I highly recommend that you read before continuing further. Don't worry, I will wait.

The first thing we have to do, is to create a stacking context on the body element (any element that contains both the footer and the #main div would work). If you don't do this, in my experience, the negative z-indexes do not work in mobile Safari, and older IEs. To create a stacking context, we only have to give it a z-index and a position:

assets/css/styles.css

body{
    font:15px/1.3 'PT Sans', sans-serif;
    color: #5e5b64;

    /* Create a page-wide stacking context 
    (so that negative margins work as you expect) */

    position:relative;
    z-index:0;
}

Now all other elements on the page with a z-index value will be stacked according to the body. Next we should assign a z-index to the #main element, so that it covers the footer (otherwise it would always be visible, fixed to the bottom of the window).

#main{
    position:relative;
    z-index:1;

    background-color: #fff;

    background-image:-webkit-radial-gradient(center, circle farthest-corner, #fff, #e2e2e2);
    background-image:-moz-radial-gradient(center, circle farthest-corner, #fff, #e2e2e2);
    background-image:radial-gradient(center, circle farthest-corner, #fff, #e2e2e2);

    padding: 120px 0 600px;
    box-shadow: 0 3px 3px rgba(0,0,0,0.2);
}

A z-index value of 1 is enough to bring the element above all other elements on the page which do not have explicit z-indexes set. In most browsers this is enough to achieve the behavior we are after, but unfortunately mobile Safari has a redrawing issue, which necessitates setting negative z-indexes on the footer. Another thing that we have to do is to set a background on the #main element, otherwise we would see the footer through it.

And here is the footer:

footer{
    height: 245px;
    color:#ccc;
    font-size:12px;

    position:relative;
    z-index:-2;

    background-color:#31353a;

    background-image:-webkit-linear-gradient(top, #31353a, #2f3337);
    background-image:-moz-linear-gradient(top, #31353a, #2f3337);
    background-image:linear-gradient(top, #31353a, #2f3337);
}

I have set a z-index value of -2. Which pushes it behind the #main div. Note that we have to give this element a height, because the UL element that is inside it has a fixed positioning and will not expand its parent to its size.

Next is the UL element inside it, which is fixed to the browser window:

/* Set a width to the outermost UL, center it and fix it to the window */

footer > ul{
    width:960px;
    position:fixed;
    left:50%;
    bottom:0;
    margin-left:-480px;
    padding-bottom: 60px;
    z-index:-1;
}

It is set to a z-index of -1, which causes it to show below the #main element, but above the footer, which is exactly what we want. This concludes the z-index trick, but there are a few more styles that are worth mentioning:

/* The four columns of links */

footer > ul > li{
    width:25%;
    float:left;
}

footer ul{
    list-style: none;
}

/* The links */

footer > ul > li ul li{
    margin-left:43px;
    text-transform: uppercase;
    font-weight:bold;
    line-height:1.8;
}

footer > ul > li ul li a{
    text-decoration: none !important;
    color:#7d8691 !important;
}

footer > ul > li ul li a:hover{
    color:#ddd !important;
}

We have to be extra careful when setting these styles, because the footer contains nested ULs which might get mixed up. To limit the effect of the styles, I am using the CSS child selector >.

Next is the company logo. The image is displayed from a sprite as a :before element.

/* The company logo */

footer a.logo{
    color: #e4e4e4 !important;
    text-decoration: none !important;
    font-size: 14px;
    font-weight: bold;
    position: relative;
    text-transform: uppercase;
    margin-left: 16px;
    display: inline-block;
    margin-top: 7px;
}

footer a.logo i{
    font-style: normal;
    position: absolute;
    width: 60px;
    display: block;
    left: 48px;
    top: 18px;
    font-size: 12px;
    color: #999;
}

footer a.logo:before{
    content: '';
    display: inline-block;
    background: url('../img/sprite.png') no-repeat -19px -70px;
    width: 48px;
    height: 37px;
    vertical-align: text-top;
}

After this, we can style the paragraph elements, which have to be transformed into brightly colored headings for each of the four sections.

footer p{
    width: 90%;
    margin-right: 10%;
    padding: 9px 0;
    line-height: 18px;
    background-color: #058cc7;
    font-weight: bold;
    font-size: 14px;
    color:#fff;
    text-transform: uppercase;
    text-shadow: 0 1px rgba(0,0,0,0.1);
    box-shadow: 0 0 3px rgba(0,0,0,0.3);
    margin-bottom: 20px;
    opacity:0.9;
    cursor:default;

    -webkit-transition: opacity 0.4s;
    -moz-transition: opacity 0.4s;
    transition: opacity 0.4s;
}

footer > ul > li:hover p{
    opacity:1;
}

footer p:before{
    content: '';
    display: inline-block;
    background: url('../img/sprite.png') no-repeat;
    width: 16px;
    height: 18px;
    margin: 0 12px 0 15px;
    vertical-align: text-bottom;
}

Another trick that I used here, is that I set the opacity of the elements to be 0.9 and I defined a transition which will smoothly animate the opacity when it changes. On hover, the opacity is set to 1, which triggers the animation.

Lastly, here are the different color themes, created with the help of a few CSS gradients:

footer p.home{
    background-color: #0096d6;

    background-image:-webkit-linear-gradient(top, #0096d6, #008ac6);
    background-image:-moz-linear-gradient(top, #0096d6, #008ac6);
    background-image:linear-gradient(top, #0096d6, #008ac6);
}

footer p.home:before{
    background-position: 0 -110px;
}

footer p.services{
    background-color: #00b274;

    background-image:-webkit-linear-gradient(top, #00b274, #00a46b);
    background-image:-moz-linear-gradient(top, #00b274, #00a46b);
    background-image:linear-gradient(top, #00b274, #00a46b);
}

footer p.services:before{
    background-position: 0 -129px;
}

footer p.reachus{
    background-color: #d75ba2;

    background-image:-webkit-linear-gradient(top, #d75ba2, #c75496);
    background-image:-moz-linear-gradient(top, #d75ba2, #c75496);
    background-image:linear-gradient(top, #d75ba2, #c75496);
}

footer p.reachus:before{
    background-position: 0 -89px;
}

footer p.clients{
    background-color: #e9ac40;

    background-image:-webkit-linear-gradient(top, #e9ac40, #d89f3b);
    background-image:-moz-linear-gradient(top, #e9ac40, #d89f3b);
    background-image:linear-gradient(top, #e9ac40, #d89f3b);
}

footer p.clients:before{
    background-position: 0 -69px;
}

This makes the headings pretty and colorful, without any images.

We're done!

I hope that you liked this simple technique. It even works on mobile devices, although you will probably want to write a media query or two so it fits into the form factor better.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

ohh cool but too much code :(

Martin Angelov

Most of it is for the styling - the part that makes the footer slide-out is only a few lines of CSS.

Wow! It is so easy :) Thank you very much for the explanation!

MontoGeek

Awesome!

Look awesome, going to use it.

How cool is that, love it. Can't wait to use it. Sound like such a nerd.

This is interesting. I was using cssstickyfooter.com because I had some pages that were pretty short in the main content area and I needed the footer to sit at the bottom. It also uses a main wrapper with a sibling footer, so I should be able to swap your technique without changing the source code around.

Even though this appears to work great even in IE7, is your technique safe enough to use on a production-level website? If browser support is on par with cssstickyfooter I think it's worth switching.

Thanks.

Jan Kupka

Hi, another solution could be to fix the position of the footer and set bottom margin on the wrapping element. http://jsfiddle.net/snLfg/

Mathew Porter

really cool effect guys and great tutorial.

Velosofy

Cool i will use this! Thanks :)

Just at the right time. ;)
A good idea, well explained. Thx.

scarfacedeb

very clever idea. nice job!

Very nice.

Sweet. Thanks for inspiration.

Amazing effect!
Is it possible to make it responsive with the dynamic height of the footer?

Rohit Tripathi

Even, I am interested to find out whether this trick will work for footer's with Dynamic height or not?

Kate Nickerson

This is cool. The only thing I am hesitant about is how this works on particularly short pages, like a page that does not fill the browser window. It might start to behave strangely.

I just implemented it successfully on my own page. I've copy pasted out all the relevant styles and HTML to here: http://jsfiddle.net/x8S2V/1/. Hope it helps

Just brilliant Martin.

Implemented this technique on my site.

Keep the good work!

Why don't you mention Roman Komarov—the inventor of the trick?

Roman Komarov

Hey, I'm not an inventor of this trick :) I saw it a few times here and there before implementing it at my site, and there was at least this tutorial beforehand: http://www.thecssninja.com/css/reveal-effect, but there were sites this one, so I'm not sure is there an origin for this trick.

Anselm Urban

Thanks for the great tutorial!

Max Requiao

very good, but just need to be responsive

sosukeinu

This is a cool effect, but how are you avoiding the main content's z-index covering links in the footer? I'm using Bootstrap with Wordpress via Roots, and adding a z-index:1; to .main effectively blocks everything in the footer. Thanks.

Md. Elias

Martin Angelov you are awesome man...excellent work...keep it up..

Amazing, thanks.

I was just wondering how the killdiscodesign.com design works, and surprise: I found this tutorial!! ...I think is very similar, but instead of applying this css-trick only to the footer, they applied to differents parts of the page, right?

Thanks again.

salvo nicolosi /bomastudio

Nice idea!

My findings:

  • giving position relative and z-index to the body is unnecessary (can you confirm?)
  • I added the following in order to make it work seamlessy no matter what the height of main (that way we can avoid relying on the padding to have a "tall enough" main):

body, html { height:100%; }

main { min-height:100%; }

Martin Angelov

Giving a z-index to the body element was needed, otherwise it didn't work in Mobile Safari. Thank you for the min-height fix!

thats a nice idea - made a sliding div with silverlight last time - that wasnt that easy like this one.

Thank you for the explanations! I just have a question about the z-index stuff you wrote on the first picture: usually, the z-index property is a layer indicator, but on the same level of the DOM, even with fixed elements. I may not be clear, but this example could be better: http://jsfiddle.net/3rMST/ So my question is about why you have to set the ul inside the footer to a greater z-index than the footer itself?
But once again, thank you for the tips!

Avangelist

Only problem - you're using fixed height. That instantly gives it a negative rating for responsive design. The challenge is whether you can achieve the same thing using progressive enhancement and responsive code.

I can only think of progressively enhancing this layout feature by setting a class to adds in the fixing and indexing with javascript if it is enabled and using media queries so it doesn't go total bezerk on small viewports.

This is super cool! Would it be possible to make it work also in responsive pages? I tried to shrink your demo to lower resolutions but it didn't work there. What should I do if the height of the footer is variable with respect to the device that is opening the webpage?

Thank you!

Great read!