Published: February 09 2016
Last updated: July 29 2021

CSS3 - Sticky Header on Scroll Example

In this tutorial I've setup an example of how to add an animated sticky header on scroll to a website using almost pure CSS with just a touch of javascript.

The header becomes 'sticky' on scroll - when the top bar containing the social share icons is scrolled out of view, in the demo this is 40px but can be changed using the LESS variables at the top of the styles.less file.

Here it is in action: (See on StackBlitz at https://stackblitz.com/edit/css3-sticky-header-on-scroll-example)


HTML for the sticky header on scroll example

The html is fairly standard with three main sections (divs) for the header, body and footer. The header section is split into two sections ("header-top" and "header-main") which are used to apply the styles for the animated sticky header functionality.

<html>
<head>
    <title>CSS3 - Sticky Header on Scroll Example</title>

    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
    <link href="styles.less" rel="stylesheet" type="text/css" />

    <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="script.js"></script>
</head>
<body>
    <div id="header">
        <div class="header-top">
            <div class="social-icons">
                <ul class="reset">
                    <li><a href="#" class="fa fa-facebook"></a></li>
                    <li><a href="#" class="fa fa-twitter"></a></li>
                    <li><a href="#" class="fa fa-google-plus"></a></li>
                    <li><a href="#" class="fa fa-github"></a></li>
                    <li><a href="#" class="fa fa-pinterest"></a></li>
                </ul>
            </div>
        </div>
        <div class="header-main">
            <div class="nav">
                <ul class="reset">
                    <li><a href="#" class="current">Home</a></li>
                    <li><a href="#">About</a></li>
                    <li><a href="#">Services</a></li>
                    <li><a href="#">Contact</a></li>
                </ul>
            </div>
        </div>
    </div>
    <div id="body">
        <h1>CSS3 - Sticky Header on Scroll Example</h1>
        
        ...

    </div>
    <div id="footer">

        ...

    </div>
</body>
</html>


LESS / CSS Styles for the sticky header on scroll example

The LESS styles are split up into sections to make them easier to follow, I've created variables for the sticky header values at the top of the file, you can edit these variables to change the size of the header sections.

There's also a handful of styles that are purely for look and feel and aren't related to the sticky header functionality, I left them in so the demo looks better and is a bit more of a real world example.


/* VARIABLES
--------------------------------------------*/
@header-top-height: 40px;      /* height of the top section of the header */
@header-main-height: 100px;    /* default height of the main section of the header */
@header-sticky-height: 60px;   /* height of the header when it's sticky */

/* GLOBAL DEFAULTS
--------------------------------------------*/
body {
    padding: 0;
    margin: 0;
    font-family: Arial;
}

a {
    transition: color 0.3s;
}

/* GENERAL CLASSES
------------------------------------------*/
ul.reset {
    margin: 0;
    padding: 0;

    > li {
        list-style: none;
    }
}

/* HEADER SECTION
--------------------------------------------*/
#header {
    position:absolute;
    top:0;
    width:100%;

    .header-top {
        height: @header-top-height;
        line-height: @header-top-height;
        background: #1b2327;
        color: #b0bec5;

        .social-icons {
            float: right;

            ul {
                li {
                    float: left;
                    margin-left: 5px;
                    font-size: 20px;

                    a {
                        color: inherit;
                        text-decoration: none;
                        display: inline-block;
                        width: 40px;
                        text-align: center;
                        line-height: 40px;

                        &:hover {
                            color: #fff;
                        }
                    }
                }
            }
        }
    }

    .header-main {
        height: @header-main-height;
        line-height: @header-main-height;
        background: #263238;
        padding: 0 20px;
        box-sizing: border-box;
        
        /* animate the transition between normal header and sticky header */
        transition: height .3s, line-height .3s;

        .nav {
            float: left;

            ul {
                li {
                    float: left;

                    a {
                        color: #cfd8dc;
                        text-decoration: none;
                        text-transform: uppercase;
                        display: inline-block;
                        padding: 0 10px;

                        &.current {
                            color: #80cbc4;
                        }

                        &:hover {
                            color: #fff;
                        }
                    }
                }
            }
        }
    }
}

/* BODY SECTION
--------------------------------------------*/
#body {
    padding-top: @header-top-height + @header-main-height;
    padding-left: 15px;
    padding-right: 15px;
    background: #eee;
    transition: padding-top .3s;
}

/* FOOTER SECTION
--------------------------------------------*/
#footer {
    background: #1b2327;
    padding: 20px;
    text-align: center;
    
    a {
        color: #b0bec5;
        text-decoration: none;

        &:hover {
            color: #fff;
        }
    }
}

/* STICKY HEADER STYLES
--------------------------------------------*/
body.sticky-header {
    #header {
        .header-main {
            height: @header-sticky-height;
            line-height: @header-sticky-height;
            position: fixed;
            top:0;
            width: 100%;
        }
    }

    #body {
        padding-top: @header-top-height + @header-sticky-height;
    }
}


Javascript / jQuery for the animated CSS sticky header on scroll example

Javascript is used to toggle the "sticky-header" class on the body tag when the header top section is scrolled in and out of view using the jQuery .scrollTop() function. The "sticky-header" class is used in the stylesheet above to switch on and off the sticky header functionality.


$(window).scroll(function () {
    // add 'sticky-header' class to the body tag when the header top is scrolled out of view
    $('body').toggleClass('sticky-header', $(this).scrollTop() > $('.header-top').height());
});


Update History

  • 29 Jul 2021 - Updated and migrated demo to StackBlitz because Plunkr stopped working
  • 09 Feb 2016 - Built with CSS3 and JavaScript

 


Need Some CSS3 Help?

Search fiverr for freelance CSS3 developers.


Follow me for updates

On Twitter or RSS.


When I'm not coding...

Me and Tina are on a motorcycle adventure around Australia.
Come along for the ride!


Comments


Supported by