Changing Navbar Style Based On Scroll

Minhee Kang
3 min readMar 18, 2019

--

As a code camp grad and in the process of looking for the next big step, I happily took on a small freelance project to create a website for an up-and-coming startup.

Upon multiple conversations about the design process, I was asked for an interesting challenge from the client — having an initial navbar upon landing on the welcome page without the logo and having a div with the logo, and once the user scrolls past the logo div, show a second logo with a navbar with a logo on the side.

The initial sketch looked like this:

First picture — upon landing // Second picture — past scroll of grey div

Below is how I approached this challenge —

1. Create the first navbar with id “nav1” in HTML

<nav id="nav1">
<a href="apply.html">Welcome</a>
<a href="faq.html">About</a>
<a href="about.html">FAQ</a>
<a href="contact.html">Contact</a>
</nav>

2. Create the second navbar with id “nav2” but with class “hidden” in HTMLCreate (I used MaterializeCSS template for Navbar)

<nav id="nav2" class="hidden">
<div class="nav-wrapper">
<a href="/" class="brand-logo">LOGO</a>
<ul id="nav-mobile" class="right hide-on-med-and-down">
<li><a href="apply.html">Welcome</a></li>
<li><a href="faq.html">About</a></li>
<li><a href="about.html">FAQ</a></li>
<li><a href="contact.html">Contact</a></li>
</ul>
</div>
</nav>
MaterializeCSS

3. Create a “hidden” class in CSS with visibility: hidden — any tag that has this class will be hidden

.hidden{   visibility: hidden;}

4. Create a “sticky” class in CSS that will keep your navbar on the top

.sticky{   position: fixed;   top: 0;
}

5. In index.js file have a onscroll function on the window to watch the scroll movement.

// set variables to the navbar1, navbar2 and both navbarsconst navbar1 = document.querySelector("#nav1");
const navbar2 = document.querySelector("#nav2");
const navbars = document.querySelector("nav")

// everytime the user scrolls, the window checks if the navbar1 // exists - aka render is complete
window.onscroll = function () {
if (navbar1) {
renderIndexHTMLNav()
} else {
renderStickyNavBar(navbar2)
}
};
/////////////////////////////////////////////////////////////////
// checks if window's y coordinate surpasses either navbar's offset // from top - aka past the navbar, make sure navbars are sticky.
// If goes back to the top of the page, remove sticky.
function renderStickyNavBar(navbar2, navbar1){
if (window.pageYOffset >= navbars.offsetTop) {
navbar2.classList.add("sticky");
navbar1.classList.add("sticky");
} else {
navbar2.classList.remove("sticky");
navbar1.classList.remove("sticky");
}
}
/////////////////////////////////////////////////////////////////
// runs the renderStickyNavBar to make sure either navbars are // stickyfunction renderIndexHTMLNav() { renderStickyNavBar(navbar2, navbar1);// set mainbottom to determine coordinate of #about-page1 (grey div // after navbar)
var mainbottom = $("#aboutpage-1").offset().top + $("#aboutpage-1").height();
$(window).on('scroll', function () {

// we round here to reduce a little workload
var stop = Math.round($(window).scrollTop());

if (stop > mainbottom) {
navbar1.classList.add("hidden");
navbar2.classList.remove("hidden");
} else {
navbar2.classList.add("hidden");
navbar1.classList.remove("hidden");
}

});

The last renderIndexHTMLNav() may be a bit tricky — but what I am trying to do here is, determine the breaking point (MAINBOTTOM), or in this case, where the first grey div with the logo ends, and determine which navbar to use.

If the navbar is below the MAINBOTTOM, the class HIDDEN is attached to the navbar2 + removes HIDDEN from navbar 1 = shows only navbar2. However, if the person scrolls back up above the MAINBOTTOM the class HIDDEN is removed from navbar2 + adds HIDDEN to navbar1 = shows only navbar1.

…and voila!

Content has been hidden but ooo navbar change!

--

--