How to: sticky top nav-bar (HTML + CSS)
Tags: html, css, navigation, webdev
Published: 2021-01-26 13:29:08

A common CSS newbie issue we face is, how to code a sticky top bar. This could be the nav-bar, a quick contact bar, quick access bar, etc. Let's assume we want to build a top nav-bar. So the requirements are:

- Nav bar should be on top
- It should stick to the top of the page
- It should scroll with the page

Before we begin, there are some things you should know, they are:

- Basic knowledge of HTML
- Basic knowledge of CSS

Excited to learn? Let's jump in!

### 1. Basic code block
To make a sticky nav-bar, let's build a nav-bar first. We will use `header` tag for this. For the rest of the content, we will use `main` tag.

```
  <header>
  </header>

  <main>
  </main>
```

### 2. Let's customize a bit with CSS

```
/* CSS */
/* imports */
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;900&display=swap');

body{
  padding: 0;
  margin: 0;
  font-family: "Lato", sans-serif;
}

header {
  height: 80px;
  background-color: #eee;
}

```
In the code above, we've added styling for body, header and main. We've also imported Lato font (because I love sans-serif fonts 😁).

#### Body tag
We remove margin and padding on `body` because when an element takes full width, default padding and margin of body interferes with the full width of the element, in this case, `header` tag. 

#### Header tag
We add a static height of 80px to the `header`, and change its color to #eee to differentiate it with rest of the content.

Let's add some content to the header/nav-bar. Generally, nav-bar has a logo and some nav-links. Logo would have an image of some sort, but for ease of the tutorial, we will just replace it with text.

#### HTML Part:
```
<header>
  <div class="logo">
    Logo
  </div>
  <ul class="nav-links">
    <li>
      <a href="https://akashdeshpande.hashnode.dev/">Blog</a>
    </li>
    <li>
      <a href="https://www.twitter.com/akashd1995">Contact</a>
    </li>
  </ul>
</header>

<main>
</main>
```

#### CSS Part:
```
/* imports */
@import url('https://fonts.googleapis.com/css2?family=Lato:wght@400;900&display=swap');

body{
  padding: 0;
  margin: 0;
  font-family: "Lato", sans-serif;
}

header {
  /* general styling */
  height: 80px;
  background-color: #eee;
  
  /* display part */
  display: flex;
  align-items: center;
  padding: 0 32px;
  justify-content: space-between;
}

.logo {
  font-size: 32px;
  font-weight: 900;
  color: #333;
}

.nav-links li {
  list-style: none;
  display: inline;
  padding-left: 32px;
}

.nav-links li a {
  color: #333;
  text-decoration: none;
}

.nav-links li a:hover {
  color: #ccc;
}
```

So far, we've added Logo, nav-links and customized them, so that they are in one line and horizontal.
Important part here is the CSS display part in `header`. We've used `display: flex` and `justify-content: space-between`. This places the logo and nav-links at the start and end of the container (header in this case) respectively. If you have not learned CSS flexbox so far, no worries, but it sure is a good thing to have in your skill set.

If we add more content to the page, the nav-bar will scroll with the page, we want it to stick to the top at all times. We will do this in the next part. The next part is important, it contains the magic ingredient that makes it all work.

### 3. Add the magic ingredient

```
/* Add this to header CSS */
position: fixed;
width: 100%;
box-sizing: border-box;
top: 0;
```

Adding `position: fixed` to `header`'s CSS makes the `header` stick to the top. We are basically done at this point, but it doesn't look good. The `header`'s width has shrunk, so we will add `width: 100%`. With this code addition, comes another issue, the width of `header` goes outside the page. We could technically fix this by adjusting the width %, but we have a better solution. Adding `box-sizing: border-box` to the CSS limits the width of header to 100% of the viewport, so it spans the whole width of the screen. A precautionary measure we could take here, although it won't be necessary, would be to add `top: 0`. This is just so that our nav-bar stays at the top of the page.

### 4. Fix code

We've completed the main step, so what remains? It is the issues we brought with our code. Let's solve those.

#### Main tag

The `main` tag contains the rest of the page. When we put `position: absolute` to `header`'s CSS, the `main` now takes up the whole page. This means that `main` will also include the area behind the nav-bar. Since that area won't be visible, we will add `padding-top: 80px`, the same as the height of the header to `main`'s CSS.

```
main {
  padding-top: 80px;
}
```

### 5. Done!

We have successfully completed our sticky top nav-bar! If you'd like to see it in action,  [see the codepen here.](https://codepen.io/akashdeshpande/pen/PoGrNGJ) 

{% codepen https://codepen.io/akashdeshpande/pen/PoGrNGJ %}