How to make a Navbar with Text Color Changing on Scrolling and Clicking with HTML/CSS/JQuery
I was working on a single page application page this week for my portfolio site and had to scour all over the internet to find how to make a navbar with text color changing on scrolling AND clicking with smooth scrolling. I am going to make your life much easier by showing you how I did this.
If you want to just skip to the code, take a look at my repo:
The final results: https://jbharwood.github.io
Okay, let’s get started!
First of all you are going to need an HTML, CSS, and Javascript file.
To save you a bit of time, this is how to get JQuery set up in your HTML file:
<head><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/ jquery.min.js"></script><script src="/js/my.js"></script></head>
HTML Snippets
//Navbar
<ul class="sidenav">
<li><a href="#home" class="menu" id="nav1">Home</a></li>
<li><a href="#projects" class="menu" id="nav2">Projects</a></li>
<li><a href="#resume" class="menu" id="nav3">Resume</a></li>
<li><a href="#contact" class="menu" id="nav4">Contact</a></li>
</ul>--------------------------------------------------------------------//Section example that you will scroll past and click to navigate to
<section href="resume" id="resume" class="section">
<h1>Resume </h1>
</section>
CSS Snippets
/* The sidebar menu */
.sidenav {
height: 100%; /* Full-height: remove this if you want "auto" height */
width: 260px; /* Set the width of the sidebar */
position: fixed; /* Fixed Sidebar (stay in place on scroll) */
z-index: 1; /* Stay on top */
top: 0; /* Stay at the top */
left: 0;
background-color: #111; /* Black */
overflow-x: hidden; /* Disable horizontal scroll */
padding-top: 20px;
}/* The navigation menu links */
.sidenav a {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 25px;
color: #818181;
display: block;
}.sidenav a:focus {
color: #4286f4;
}.sidenav a:hover {
color: white;
}.sidenav a:active {
color: #4286f4;
}//Changes the color of text once the text is clicked in the navbar
.sidenav a.selected{
color: #4286f4;
}
JS/JQuery Snippets
$(document).ready(function(){//Click function// Add smooth scrolling to all links on click
$("a.menu").on('click', function(e) {// Make sure this.hash has a value before overriding default behavior
if (this.hash !== "") {
// Prevent default anchor click behavior
e.preventDefault();// Store hash
var hash = this.hash;$('a.menu').removeClass('selected');
$(this).toggleClass('selected');// Using jQuery's animate() method to add smooth page scroll
// The optional number (800) specifies the number of milliseconds it takes to scroll to the specified area
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 600, function(){// Add hash (#) to URL when done scrolling (default click behavior)
window.location.hash = hash;
});
} // End if
});//Scroll Function
// adds and removes selected class when the section is reached with the scroll
$(document).bind('scroll',function(e){
$('section').each(function(){
if ($(this).offset().top < window.pageYOffset + 10 && $(this).offset().top + $(this).height() > window.pageYOffset + 10){
window.location.hash = $(this).attr('id');if($(this).attr('id') == "home"){
$('a.menu').removeClass('selected');
$("#nav1").toggleClass('selected')
} else if($(this).attr('id') == "projects"){
$('a.menu').removeClass('selected');
$("#nav2").toggleClass('selected')
} else if($(this).attr('id') == "resume"){
$('a.menu').removeClass('selected');
$("#nav3").toggleClass('selected')
} else if($(this).attr('id') == "contact"){
$('a.menu').removeClass('selected');
$("#nav4").toggleClass('selected')
}
}
});
});
//Scroll Bug function// fixes the bug that caused scrolling up to be faster
function wheel(event) {
var delta = 0;
if (event.wheelDelta) {(delta = event.wheelDelta / 120);}
else if (event.detail) {(delta = -event.detail / 3);}handle(delta);
//commented out because it caused bug in DOM // if (event.preventDefault) {(event.preventDefault());}
// event.returnValue = false;
}function handle(delta) {
var time = 1000;
var distance = 300;$('html, body').stop().animate({
scrollTop: $(window).scrollTop() - (distance * delta)
}, time );
}if (window.addEventListener) {window.addEventListener('DOMMouseScroll', wheel, false);}
window.onmousewheel = document.onmousewheel = wheel;});
You might be wondering why I didn’t just use smooth scrolling like this:
html {
scroll-behavior: smooth;
}
I didn’t go with this approach because it was causing problems with clicking on the navbar to get to the corresponding section. The smooth scrolling would work but it wouldn’t go to where I wanted it to on a click. So the approach that I went with was to apply smooth scrolling to the the JQuery scrolling and clicks functions without using CSS.
I’ll breakdown the 3 JQuery functions that I used:
Click Function
I am adding and removing the .selected class to the text in the navbar when it is clicked and the color of the text is changing when it is selected. Smooth scrolling is applied to it on click.
Scroll Function
I am also adding and removing the .selected class when the corresponding section is scrolled past. The menu selected class is cleared once a section is scrolled past so that there is not multiple navbar texts with the .selected class.
Scroll Bug Function
This is my fix to the HTML smooth scrolling bug that I mentioned earlier. Another bug that stemmed from this was that the smooth scrolling wasn’t working when I was scrolling up the page. It would accelerate much faster scrolling up when it was scrolling down. This function makes it scroll evenly going up and down. I commented out the event.preventDefault conditional because it was causing the problems in the DOM when scrolling.
I hope this helps!