DEV Community

Cover image for One Line - Sticky Header using CSS
Akhil Arjun
Akhil Arjun

Posted on

One Line - Sticky Header using CSS

How many times have we come across a situation where you want the header of a website to remain on top of everything even if you scroll past it.

Or, to have a navigation bar that is beneath a hero-banner to stick to the top once we scroll past it.

Or even for a navigation bar to stay at the bottom of a mobile website.

I know

We have been in this sticky situation (pun intended) over and over. The time has come we solve this once and for all.

The best part is, we will do it in one-line 😎

CSS



nav {
    position: sticky; top: 0;
}


Enter fullscreen mode Exit fullscreen mode

I know what you are thinking, that is two lines! OK I admit I got carried away with the one-line heading, but I assure you it is still awesome 😍

Let's see some demo's and understand how it works

Demo 1: The nav-bar that just sticks

Let's try and understand what is happening here.

The markup I have used is pretty simple

HTML



<body>
  <nav>
    <ul>
      <li><a href="#first">First</a></li>
      <li><a href="#second">Second</a></li>
      <li><a href="#third">Third</a></li>
    </ul>
  </nav>
  <section id="first">First Section</section>
  <section id="second">Second Section</section>
  <section id="third">Third Section</section>
</body>


Enter fullscreen mode Exit fullscreen mode

CSS



html {
  margin: 0;
  padding: 0;
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body nav {
  position: sticky;
  top: 0;
}
ul {
  width: 100%;
  display: flex;
  justify-content: flex-end;
  box-sizing: border-box;
  padding: 20px;
  background: #fff;
}
li {
  list-style: none;
  margin-right: 20px;
  font-size: 25px;
  font-weight: bold;
}
li a {
  text-decoration: none;
  color: #1ac;
}
section {
  height: 100vh;
  display: grid;
  place-items: center;
  font-size: 50px;
  font-weight: bold;
  background: #eee;
}


Enter fullscreen mode Exit fullscreen mode

Of all that mark-up the most important two lines where all the magic happens is



...
body nav{
    position: sticky;
    top: 0;
}
...


Enter fullscreen mode Exit fullscreen mode

What it tells the browser is to stick this element to the viewport when its top position value is 0;

An element with position: sticky; is positioned based on the user's scroll position.

A sticky element toggles between relative and fixed, depending on the scroll position. It is positioned relative until a given offset position is met in the viewport - then it "sticks" in place (like position: fixed).

Now that we understood how it works let us see two more use-cases of sticky.

Demo 2: Nav-bar below a hero banner.

Here, the nav-bar is below the hero banner. So it acts relative until its offset from the top is not 0. The moment the offset value reaches 0 it sticks to the top of the viewport.

Demo 3: Application with a sticky header and footer

Notice how we have styled footer element.



footer {
    ...
    position: sticky;
    bottom: 0;
    ...
}


Enter fullscreen mode Exit fullscreen mode

There you go! We are now officially sticky! πŸ±β€πŸ‘€βœŒ

Do you know what else is sticky? Coffee spilled on a table! My days are fueled with coffees and only coffees. So I know, you know what we all should do 🀞


Buy Me A Coffee

Keep Hacking β˜•

References

Top comments (11)

Collapse
 
gsarig profile image
Giorgos Sarigiannidis • Edited

position:sticky is great and I use it whenever I can instead of a JavaScript solution. One caveat that you need to consider, though, is that it won't work if a parent element has an overflow:hidden;

Sometimes this might be a deal-breaker.

Collapse
 
akhilarjun profile image
Akhil Arjun

Yeah but the whole point of using sticky is when we have a scrollable element. So if we have overflow hidden. We should always go for position:absolute

Collapse
 
gsarig profile image
Giorgos Sarigiannidis • Edited

A not so rare scenario of those two conflicting would be to have a container at the top of your DOM (e.g. right after the <body>) with an overflow: hidden; in order to avoid vertical scrollbars (caused by some burger menu or whatever). Then, deeper in the DOM you might want to have your sticky element.

In that scenario, you would need to either figure another way to get rid of the vertical scrollbars or use JavaScript to stick the element. It doesn't matter if the container only has its overflow-x set to hidden and not overflow-y; it will mess with the child element's position: sticky anyway.

Collapse
 
sirawit profile image
Dragodzs

wow, that awesome!

Collapse
 
akhilarjun profile image
Akhil Arjun

Thanks mate πŸ•ΊπŸ‘Ύ

Collapse
 
majurgens profile image
majurgens • Edited

This was so super simple, I implemented it immediately.

However, I have this one page where I cannot make this work properly. I cannot work out what is going wrong. See
https://www.edcint.co.nz/cgi-bin/webalbum_search.cgi?searchterms=.&mode=search&searchfile=.webalbum_search_data_public.conf_2&albumtophtmldir=%2Fpublic%2Fdata%2F&resultnumber=0&linkback=%2Fpublic%2Fdata%2Findex.shtml&modtime=0&shortform=n&submit=&approxsearch=1&showimages=1&showvideos=1&showfolders=1&showwithcomments=1&showwithnocomments=1&imageheight=200&displayimageinfo=1&maxresults=10&modtimedays=0&ssdelay=15

The header seems to come and go as you scroll down the page. Once you reach the bottom of page (lazy loading and infinite scroll are in play here), then the header works ok.

In a related page, that uses a lot of the same code (same lazy loading and infinite scroll), it works just fine
edcint.co.nz/public/data/scenery (copy and paste, don't click this link)

Any ideas?

Collapse
 
mbaapohz profile image
Mbaapoh

Am glad, I found this

Collapse
 
akhilarjun profile image
Akhil Arjun

Glad it helps πŸ•ΊπŸ‘Ύ

Collapse
 
donwiss profile image
Don Wiss

This is beautifully simple. But one is left with the problem of jumping to an anchor on the page is now off.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.