How to Create an On Scroll Fixed Navigation Bar with CSS

css
Published on December 30, 2018

Earlier to create a navigation bar which would become fixed on scrolling, there was no way to do it without Javascript. The window.onscroll event needed to be listened for. The offset position of navigation bar had to be calculated first, then ... then the CSS position: fixed was applied to the navbar to make it fixed.

The process worked, but it had it own glitches, specially performance issues — it is never a good idea to listen for an onscroll event. For tiny cases you may get away, for more complex cases the application will start stuttering.

But now things have changed in modern browsers. You can create a sticky element using just CSS !

Demo

Click here to see demo

Download codes for the demo

Switching Between Relative & Fixed Positioning with position: sticky

position: sticky comes between position: relative and position: fixed. It behaves like a relatively positioned element within its parent, but when it crosses a specified threshold in the viewport (screen), it becomes "stuck" to the screen and becomes a fixed element.

Consider the following CSS :

.sticky-navbar {
    position: sticky;
    top: 15px;
}

When the distance of the element is more than 15px from the top of the screen, it will behave like a normal element. During scrolling when the distance becomes 15px (or less) from the top, it becomes fixed. Furthermore during scrolling when distance becomes more than 15px, it becomes a normal element once again.

CSS to Make an Element Sticky

For the following HTML :

<body>
    <div id="logo-container"></div>
    <div id="nav-container">Navigation Container</div>
    <div id="main-container"></div>
</body>

The CSS for #nav-container would be :

.sticky-navbar {
    position: -webkit-sticky;
    position: sticky;
    top: 0;
}

That's it. No more code required to make an element fixed on scrolling !

Gotchas to Prevent in Sticky Position

  1. Don't place the navbar within a parent container, which would later get hidden when scrolled past it. For example the below markup won't work :

    <div id="nav-outer-container">
        <div id="nav-container">Navigation Container</div>
    </div>
    

    It is because the navbar (which is a child of the outer container) would be visible only when the parent is visible. Once the user scrolls beyond the outer container, it gets hidden and the child gets hidden too.

    A sticky element is fixed until it reaches the boundary of the parent container.

  2. Don't forget to add top CSS for the sticky navbar.

    Without either a top, bottom, right or left property, it is the same as relatively positioned, so it won't become stuck.

Browser Compatibility

Chrome, Firefox & Edge support position: sticky. Safari also supports it with position: -webkit-sticky

For older browsers you can use Stickybits as a polyfill.

In this Tutorial