Published:
Last updated:

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

 


Subscribe or Follow Me For Updates

Subscribe to my YouTube channel or follow me on Twitter, Facebook or GitHub to be notified when I post new content.

Other than coding...

I'm currently attempting to travel around Australia by motorcycle with my wife Tina on a pair of Royal Enfield Himalayans. You can follow our adventures on YouTube, Instagram and Facebook.


Need Some CSS3 Help?

Search fiverr to find help quickly from experienced CSS3 developers.



Supported by