Welcome to a quick tutorial on how to create sticky headers in HTML and CSS. So you want a header or navbar to stay at the top of the page?
There are 2 easy ways to create a sticky header in HTML CSS:
<header style="position:sticky; top:0;">
This will stick the header to the top as the user scrolls down.<header style="position:fixed; top:0; left:0; width:100%">
This will permanently fix the header at the top.
Yep, it’s that simple. But let us walk through detailed examples in this guide, read on!
TABLE OF CONTENTS
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
EXAMPLE CODE DOWNLOAD
Just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
SORRY FOR THE ADS...
But someone has to pay the bills, and sponsors are paying for it. I insist on not turning Code Boxx into a "paid scripts" business, and I don't "block people with Adblock". Every little bit of support helps.
Buy Me A Coffee Code Boxx eBooks
STICKY HEADERS
All right, let us now get into the examples of the sticky headers in HTML and CSS.
TUTORIAL VIDEO
EXAMPLE 1) STICK HEADER AS THE USER SCROLLS
1A) DEMO
1B) THE HTML
<!-- (A) NAV BAR -->
<nav id="page-nav">TOP NAV</nav>
<!-- (B) STICKY HEADER -->
<header id="page-head">HEADER</header>
<!-- (C) CONTENTS -->
<main id="page-main">CONTENTS</main>
There are 3 sections on this dummy page.
<nav id="page-nav">
A top navigation bar, this one does not stick.<header id="page-head">
The sticky page header.<main id="page-main">
Main contents.
1C) THE CSS
/* (A) STICKY HEADER */
#page-head { position: sticky; top: 0; z-index: 9; }
- As in the above snippet, we only need to add
position: sticky; top: 0;
to create the sticky header. z-index: 9
will make sure that the header is layered above other elements; Just give this a higher number if it gets covered by another “floating element”.
EXAMPLE 2) FIXED HEADER
2A) DEMO
2B) THE HTML
<!-- (A) STICKY HEADER -->
<header id="page-head">HEADER</header>
<!-- (B) CONTENTS -->
<main id="page-main">CONTENTS</main>
This should be very straightforward, just your usual:
<header id="page-head">
Fixed header.<main id="page-main">
Contents.
2C) THE CSS
/* (A) HEADER */
#page-head {
position: fixed; top: 0; left: 0; z-index: 9; /* fixed at top */
width: 100%; height: 60px; padding: 10px; /* dimensions */
display: flex; align-items: center; /* alignment */
}
/* (B) CONTENTS */
/* add top spacing to prevent being covered by header */
#page-main { margin-top: 80px; padding: 10px; }
This is an old-school method, when we didn’t have sticky
to work with. A little bit roundabout:
- Set the header.
position: fixed; top: 0; left: 0; z-index: 9;
Permanently fixed at the top of the window.width: 100%; height: 60px; padding: 10px;
Set the dimensions of the fixed header bar.display: flex; align-items: center;
Actually optional, but makes the header look nicer.
- The header is permanently fixed at the top of the window, and we don’t want the contents to be covered under it. Thus,
margin-top: 80px
will deliberately leave empty space at the top for the header.
EXAMPLE 3) DETECTING WHEN A HEADER IS “STUCK”
3A) DEMO
3B) THE HTML
<!-- (A) NAV BAR -->
<nav id="page-nav">TOP NAV</nav>
<!-- (B) STICKY HEADER -->
<header id="page-head">HEADER</header>
<!-- (C) CONTENTS -->
<main id="page-main">CONTENTS</main>
Look no further, this is the same as the previous example. But we will be applying a different background color to the header navbar when it is “stuck” on top.
3C) THE CSS
/* (A) STICKY HEADER */
#page-head { position: sticky; top: -1px; z-index: 9; }
#page-head.stuck { background: red; }
How do we detect if the header navbar has been “stuck” to the top? Sadly, there is no CSS :stuck
pseudo-class, but we do have a little trick to detect “stuck”. Take note of how we displace the header to top: -1px
.
3D) THE JAVASCRIPT
window.addEventListener("load", () => {
const observer = new IntersectionObserver(
([e]) => e.target.classList.toggle("stuck", e.intersectionRatio < 1),
{ threshold: [1] }
);
observer.observe(document.getElementById("#page-head"));
});
Credits to David Walsh for this nifty trick.
- Basically, the
top
position will shift when the header is stuck. - We are simply using Javascript
IntersectionObserver
to detect this change. - When the header is stuck, we apply a
.stuck
CSS class to it.
EXTRAS
That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.
DESIGN CONSIDERATIONS – MOBILE SUPPORT
Before you plaster sticky headers all over your website, please consider if it adds more to the usability of the website. “Sticky interface” may work well on big screens, but it becomes a problem on small mobile screens instead – They don’t have a lot of space, and having a fixed header makes even less space to display content.
LINKS & REFERENCES
- Position – MDN
- Intersection Observer – MDN
- How to Detect When a Sticky Element Gets Pinned – David Walsh
- Freeze Table Rows & Columns – Code Boxx
- Sticky Footers – Code Boxx
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!