Post

Build A Scroll-Spy Navbar (Solution to Code Challenge #9)

Draft updated on Invalid Date
Default avatar

By William Imoh

Build A Scroll-Spy Navbar (Solution to Code Challenge #9)

This tutorial is out of date and no longer maintained.

Introduction

Last week we put out a challenge to build out a scroll-spy navbar. Scroll-spy navbars are great and highlight the navbar menu when a specific element or portion of the page comes into view. Are you yet to take the challenge? Do so and showcase your submission in the comment section of the post or on Twitter using the hashtag #scotchchallenge to receive reviews. This challenge can be completed using any language, tool, technique, or technology.

In this post, we shall be solving this challenge by implementing the scroll-spy on the provided base code using Vanilla JavaScript and in-view.js. This will be achieved in about 11 lines of code.

In-view.js is a JavaScript utility that notifies us when a DOM element enters or exits a viewport.

The Base

Base code was provided for this challenge which consisted of HTML and CSS code to deliver the base structure and style of the page.

The HTML

In the HTML, a nav element is used to create the navbar and a section element houses the body of the page. The body contains headers of different sizes created with h1 and h2 elements. Bulma classes were used to style the various headers and the navbar.

<nav class="navbar is-info is-fixed-top">
  <div class="container">
    <div class="navbar-menu">
       <div class="navbar-start">
         <a class="navbar-item" href="#one" id="link-one">One</a>
         <a class="navbar-item" href="#two"  id="link-two">Two</a>
         <a class="navbar-item" href="#three" id="link-three">Three</a>
         <a class="navbar-item" href="#four" id="link-four">Four</a>
         <a class="navbar-item" href="#five" id="link-five">Five</a>
        <a class="navbar-item" href="#six" id="link-six">Six</a>
      </div>
    </div>
  </div>
</nav>

<section class="section">
  <div class="container">
    <h1 class="title">The List</h1>

    <div class="block content">
      <h2 class="title" id="one">One</h2>
      <p>Lorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset</p>
      <h3>Sub Chakra</h3>
      <p>glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouwsLorem ipsum sit dolor aset glouws</p>
      [...]
    </div>
</section>

The CSS

While Bulma classes have been used to style the page, the padding-top property of the body element is styled to accommodate the fixed navbar.

body {
  padding-top: 3.25rem;
}

No JavaScript was included in the base code provided.

The Technique

In-view.js provides a seamless way to handle elements when they enter and exit the viewport, most likely during scroll. Once we scroll to a section, the class list of the corresponding navbar menu is updated. Bulma provides an is-active class which highlights a menu item when active. This class will be toggled on and off whenever a menu item enters or leaves the viewport respectively.

Installing in-view

While in-view can be installed using the node.js package manager npm, we shall be importing the script from a CDN.

In the CodePen, add a new external script from here.

Implementing Spy-Scroll

Using the on method in in-view, we state actions that will be carried out when an element enters or exits the viewport. The on method takes two parameters with the first being either enter or exit and the second is a callback function with an argument which is the element entering or leaving the viewport.

Also, it is necessary to minimize the viewport area being watched so, we don’t have two elements in the viewport at a time. This is achieved by specifying an offset of the viewport using the offset() method.

Note: That in this demo, only the headers are tracked during scroll and subsequent use cases may require tracking the whole content of a section during scroll.

While registering these methods on a single DOM element, we would like to spy on all the headers of the menu items at once. This will be achieved using the forEach() method to traverse the elements and apply an in-view function to each element. This is done with:

// In-view function
const handleView = item => {
  const linkEl = document.querySelector(`#link-${item}`);

  let offsetHeight = 0.6*(window.innerHeight)
  inView.offset({
    bottom:offsetHeight
  });

  inView(`#${item}`)
    .on("enter", () => linkEl.classList.add('is-active'))
    .on("exit", el  => linkEl.classList.remove('is-active'))
};

// Apply method on each DOM element
["one", "two", "three", "four", "five", "six"].forEach(handleView);

Once we created a function that takes an argument of the unique identifier in each DOM element, we apply the in-view method and used the forEach() method to spread the function across the elements. Zero rocket science! Also, it can be seen that the viewport is offset by 60% from the bottom, this means that the header has to enter the top 40% of the page to be considered in view.

Here is the final product:

https://codepen.io/Chuloo/pen/vjWBmX?editors=1010

Conclusion

In this post, we successfully completed the challenge by implementing the scroll-spy on the navbar using in-view.js and an is-active Bulma class to highlight the navbar. This is just a simple use case of in-view.js, feel free to try it out in other cool UI tricks and techniques while building awesome stuff. Feel free to leave your comments and feedback in the comment section and let’s watch out for the next challenge. Happy coding!!

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
William Imoh

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel