How to use offset_top options for sticky js

To create a sticky navbar, you use the

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

7 CSS property to “stick” your navbar to the viewport, and

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

8 to make it stick to its parent element.

In this post, you’ll learn what all of this means, and how to make a sticky navbar for your own site.

Let’s go!

What Is a Sticky Navbar?

But before we proceed, we need to clear one thing up. What exactly do you mean by “sticky”?

You see, in the world of CSS,

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

9 means something very specific. In fact, there are two settings you use to “stick” an element to a certain part of the screen while the visitor scrolls. These are:

`position: sticky; `Code language: CSS (css)

or …

`position: fixed; `Code language: CSS (css)

There’s a big difference between them:

  • `@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css) 0 elements stay in the same position on the viewport, regardless of scrolling. So as you scroll down the page, they seem to ‘float’ over the content.
  • `<section id=""> <article>
    <h2></h2>  
    <p></p>  
    
    </article> </section> `Code language: HTML, XML (xml) 9 elements are similar – they stay in the same position on the viewport, regardless of scrolling, but only within their parent element. When the viewport reaches the end of a sticky element’s parent, it will behave like a relatively positioned element.

In this post, you’ll learn how to make a commonly used version of the sticky navbar – one that starts out positioned in your site’s header, but not right at the top. Then, as the visitor scrolls past, it “sticks” to the top of the screen, and stays in view as they scroll.

Here’s how you do it…

1) Make a Simple Website for the Sticky Navbar

First, let’s build a site for the sticky navbar to go in. We’ll make a simple one-page site with some jokes from famous comedians.

Each link in our sticky navbar will point to a different section of the site – so we’ll use a few

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

2 elements, with some space for content inside. Here’s the structure:

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

And here’s the CSS:

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

We can then style each individual section via it’s

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

3, so the section for the comedian Bill Hicks could look like this:

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

And after Googling some jokes, and adding some more styles for each section, we get this:

2) Build the Navbar

Now to add the navbar, which we’ll place below the

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

4 section in the markup. First the HTML:

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

Then some CSS to make it look more presentable, and to position it at the top of the page:

`nav { background-color:

3a24f0;

padding: 10px; text-align: center; width: 100%; / Pay special attention here! / position: sticky; top: 0px; } nav a { color: white; text-decoration: none; margin: 0px 10px; } nav a:hover { text-decoration: underline; } @media (prefers-reduced-motion: no-preference) { html {

scroll-behavior: smooth;
} } `Code language: CSS (css)

Which turns out like this:

How this Makes the Navbar Sticky

So how does this work?

Well, as you may remember,

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

0 sticks an element to the viewport, and

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

9 sticks it to its parent element. But here, our navbar is below the header in the markup, rather than being a child of it. So its parent is

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

7!

We gave the element a

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

8 value of 0. Until the element reaches that position in the viewport, it will behave as if it has

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

9. Once the top of the element reaches the top of the viewport,

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

0 kicks in, and it behaves as if it has

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

1.

This is a really cool solution and means you don’t have to use JS to create this effect. However, it only works when the navbar’s parent is

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

2. If that’s not possible in your case, don’t worry! There’s another way…

3) Creating a Sticky Navbar with JS – Initial Positioning

Let’s say, for whatever reason, your navbar has to be a child of your

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

4, but you still want to make it sticky.

You HTML may look something like this:

`<section id="header"> <article>

<h2>Let's read some jokes!</h2> 
</article> <nav id="main-nav">
<a href="
# header">Home</a>
<a href="
# tim-vine">Tim Vine</a>
<a href="
# bill-hicks">Bill Hicks</a>
<a href="
# stewart-francis">Stewart Francis</a> </nav> </section> `Code language: HTML, XML (xml)

Now

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

4‘s parent is

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

4, so if we use position sticky it won’t stay in view after we’ve scrolled past it. For now, let’s just position it relatively:

`

main-nav {

background-color:

1e1e1e;

padding: 10px; text-align: center; width: 100%; position: relative; box-sizing: border-box; height: 45px; } `Code language: CSS (css)

At the moment, it’s just a standard navbar…

4) Creating a Sticky Navbar with JS – the Sticky Effect

Because the navbar’s parent isn’t

`@import url('https://fonts.googleapis.com/css2?family=Caveat&family=Poppins:wght@300&display=swap'); body { font-family: poppins, sans-serif; margin: 0px; } section { min-height: 100vh; } article { width: 90%; max-width: 600px; padding: 20px; margin: 0px auto; } h2 { text-align: center; padding: 40px 0px 0px 0px; font-size: 3em; } p { font-size: 1.5em; text-align: center; } `Code language: CSS (css)

7, we’ll actually have to use

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

7 to stick the navbar to the top of the screen.

Let’s put this into a class:

`

main-nav.sticky {

position: fixed; top: 0; } `Code language: CSS (css)

Next we need to add this class to the

main-nav element when the user scrolls past it.

To know if the visitor has scrolled past the navbar, we need to check two things:

  1. How far the navbar is from the top of the screen
  2. How far the visitor has scrolled

We can find out (1) with the following:

`position: fixed; `Code language: CSS (css)

0

For (2), we first need to add an event listener to detect scrolling, and then store the scroll position in a variable.

`position: fixed; `Code language: CSS (css)

1

Adding the sticky class to the navbar

Great, we now have the information we need. When the user scrolls, we’ll check whether the new scroll position (

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

  1. is greater than the navbar’s position (

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

  1. and if so, add the class.

But hold on a second!

When we do this, we’re taking a relatively positioned element, and making it absolute. This takes it ‘out of the flow’ of the markup, and any elements below it will jump upwards to fill the empty space it left behind.

To offset this, we will simply add 45px of padding to the first element after the header, which in this case is the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

0 element. Since the navbar is 45px high, this will prevent the content from ‘jumping’ upwards:

The new class:

`position: fixed; `Code language: CSS (css)

2

…and the JS that makes it all work:

`position: fixed; `Code language: CSS (css)

3

Give it a try below!

5) Highlight Active Navbar Sections

With navbars, it’s customary to highlight the section of the site that the visitor is currently on.

The logic here is very similar to what we’ve just done with the navbar. First, we create a class to flip the colors of the navbar link when it’s active:

`position: fixed; `Code language: CSS (css)

4

I also added

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

1 of padding to

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

2, to give it a litle breathing room, and added the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

3 class to the first section – since the user will land on that section:

`position: fixed; `Code language: CSS (css)

5

Now, all we have to do is add and remove this class from the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

4 elements within the navbar when the relevant section is in view.

The new JS we need for this is shown below:

`position: fixed; `Code language: CSS (css)

6

Going through the new additions line-by-line:

`position: fixed; `Code language: CSS (css)

7

This grabs all the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

4 elements within the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

6 element and puts them into an array called

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

7.

`position: fixed; `Code language: CSS (css)

8

We’re gonna loop through each of our links, and run the code inside this block. Within this block, we’ll use the alias ‘link’ to refer to our links.

`position: fixed; `Code language: CSS (css)

9

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

8 refers to the target URL of the link. This line scans the page for an element with that name, and if it finds one, stores it in the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

9 variable.

Since the links point to the sections within the page, this will return the section that the link is pointing to!

Check if the Section is Currently On-Screen

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

0

This should be familiar to you – it’s similar to the logic we used previously. There are two differences though:

  1. This time, we also check whether the bottom of the element (i.e., its offsetTop plus its height) is greater than the scroll position. If it is, that means the user has scrolled past it, so we can remove the

    `<section id="header"> <article>

    <h2>Let's read some jokes!</h2>  
    
    </article> </section> <nav> <a href="

    header">Home</a>

    <a href="

    tim-vine">Tim Vine</a>

    <a href="

    bill-hicks">Bill Hicks</a>

    <a href="

    stewart-francis">Stewart Francis</a>

    </nav> `Code language: HTML, XML (xml) 3 class.
  2. I’ve added an extra 150 pixels to

    `nav { background-color:

    3a24f0;

    padding: 10px; text-align: center; width: 100%; / Pay special attention here! / position: sticky; top: 0px; } nav a { color: white; text-decoration: none; margin: 0px 10px; } nav a:hover { text-decoration: underline; } @media (prefers-reduced-motion: no-preference) { html {
    scroll-behavior: smooth;  
    
    } } `Code language: CSS (css) 1. Why? Well, imagine you’ve scrolled 1 pixel above the top of a section.

In this case, your whole screen, apart from that 1 pixel, is taken up by that section. So even though the top of the viewport hasn’t officially reached that section, it really feels like that’s the one you’re “on”. Also, remember that 45px of the screen is taken up by the sticky navbar.

Adding the 150px buffer helps adjust for this a bit.

Of course, you don’t have to use 150px – use whatever feels right according to the screen size and the amount of content on the page.

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

1

If the above conditions are met, we’ll add the

`<section id="header"> <article>

<h2>Let's read some jokes!</h2>
</article> </section> <nav> <a href="

header">Home</a>

<a href="

tim-vine">Tim Vine</a>

<a href="

bill-hicks">Bill Hicks</a>

<a href="

stewart-francis">Stewart Francis</a>

</nav> `Code language: HTML, XML (xml)

3 tag to the link. If not, we remove it. Then we just close our brackets and we’re all set!

What if You Want a Truly Fixed Navbar?

You might be wondering, what would you do if you wanted the navbar at the top of the screen all the time – without this sticky effect?

It’s easy – just set up the

`nav { background-color:

3a24f0;

padding: 10px; text-align: center; width: 100%; / Pay special attention here! / position: sticky; top: 0px; } nav a { color: white; text-decoration: none; margin: 0px 10px; } nav a:hover { text-decoration: underline; } @media (prefers-reduced-motion: no-preference) { html {

scroll-behavior: smooth;
} } `Code language: CSS (css)

3 element with

`section

bill-hicks {

background: rgb(123,211,232); background: linear-gradient(135deg, rgba(123,211,232,1) 0%, rgba(232,123,165,1) 0%, rgba(255,50,50,1) 100%); color:

40081a;

} `Code language: CSS (css)

7 and

`nav { background-color:

3a24f0;

padding: 10px; text-align: center; width: 100%; / Pay special attention here! / position: sticky; top: 0px; } nav a { color: white; text-decoration: none; margin: 0px 10px; } nav a:hover { text-decoration: underline; } @media (prefers-reduced-motion: no-preference) { html {

scroll-behavior: smooth;
} } `Code language: CSS (css)

5:

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

2

Then get rid of the JS that added the sticky class, as we don’t need that now. And hey presto!:

6) Throttling the Event Listener

Just one more step before we’re finished – if you’re using the JS approach, it’s a good idea to throttle the functions in the event listener.

How to use offset_top options for sticky js

No, not that kind of throttling! Here’s what I mean…

When the user scrolls, it might trigger 30, 50, maybe even 100 events every second. Not a huge deal in our little project here, but in larger projects with more extensive functions, this could be an unnecessary performance hit.

The solution is throttling. Basically how it works is, every time you call the function, you start a timer. If you try to call the function again before the timer runs out, the throttler won’t allow it.

So how do we set this up? Easy – use a library! Lodash is a common one. Just download it and load it in your HTML file:

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

3

Once that’s done, we just pull our code out of the event listener, and into a function:

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

4

Now, we’d normally call that function from inside the event listener:

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

5

However, with Lodash we just put that function into the throttler, like this:

`<section id=""> <article>

<h2></h2>
<p></p>
</article> </section> `Code language: HTML, XML (xml)

6

The 100 here just means 100 milliseconds. When our function is called, a 100-millisecond timer starts, and the function won’t run again until that timer runs out.

Final Result

Pretty cool eh? By loading the Lodash library, you open up a whole world of performance and tuning functions you can use, to save you having to write all that code by yourself.

Another fantastic library you might want to check out is fullPage.js. This will really take your one-page site to the next level. With fullPage, the different sections of your site are locked at the size of the viewport, and when the user scrolls, they scroll down to the next section (and there are some fancy animations to get them there, as well as smooth scrolling).

Your browser does not support the video tag.

This makes everything we’ve been talking about here much easier – it’s easy to check which navbar link is active because one page is active at a time. No need to mess around calculating offsets. So have a look at fullPage.js and see what you think!

How to use offset function in JavaScript?

The offset() method set or returns the offset coordinates for the selected elements, relative to the document. When used to return the offset: This method returns the offset coordinates of the FIRST matched element. It returns an object with 2 properties; the top and left positions in pixels.

How to position sticky in JavaScript?

The sticky element has a parent or ancestor with overflow: hidden , overflow: auto , or overflow: scroll . The solution is to remove the overflow property. The element with position: sticky has the same height with its parent. You may remove the parent element or change the dom level of the element.

How do I get CSS to stick to the top when scrolling?

To get the header to stay in place when scrolling, you can use CSS position: fixed; property on the header element. This will allow the header to stay at the top of the page, even when the user scrolls up or down the page.

How do I make a div stick to the top?

Add CSS.

Set the position to “sticky”. For Safari, use -webkit-sticky..

Set the top property to 0..

Add the background-color, padding, and font-size properties..