Scroll with fixed navigation

I recently made a website which was just one page with a fixed navigation bar at the top of the page. The idea was that when you click on the navigation links the page scrolls to the relevent section on the page.
If the user was also to use the scrollbar to move up and down the page, I also wanted the relevent navigation link to highlight.

You can view the afore-mentioned website here.
To see the code you can always right-click and then click on ‘view page source’.

The navigation.

Put the navigation div in your header and give it a fixed position and 100% width in the css.

#navigation {position:fixed; width: 100%;}

My css for the unordered list is like this.

#nav {list-style-type:none;}
#nav li {display:inline-block; margin:0; margin-right:15px; color:#929292; transition: color 0.35s; -webkit-transition: color 0.35s; /* Safari */}

For the div#main-nav you could do something like this.

#main-nav {max-width:1000px; margin:0 auto;}
<div id="navigation">
<div id="main-nav">
	<ul id="nav">
		<a href="#"><li id="biogs">biography</li></a>
		<a href="#"><li id="teachings">teaching</li></a>
		<a href="#"><li id="linkss">links</li></a>
		<a href="#"><li id="contacts">contact</li></a>
		<a href="#"><li id="socials">social</li></a>
		<a href="#"><li id="picturess">pictures</li></a>
	</ul>
</div>
</div><!----End navigation----->

Section Divs.

Sections with any kind of content that you want.

As the navigation div has position:fixed the div underneath containing the content must be padded a fair bit at the top. My css looks like this.

#full {max-width:900px; width:95%; margin:0 auto; padding-top:100px; clear:both;}

The html.

<div id="full">

<div id="biog">
		<h2>Biography</h2>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. </p>
</div><!-----End biog----->
	
<div id="teaching">
		<h2>Teaching</h2>
		<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. </p>
</div><!----End div teaching---->	
	
<div id="links">
		<h2>Links</h2>
		<p>Proin viverra massa at turpis adipiscing, nec tempus felis dictum.</p>
</div><!-----End div links----->
	
<div id="contact">
	<h2>Contact Me</h2>
 <p>Etiam tincidunt diam dolor, sit amet vestibulum nulla rhoncus at. Mauris quis purus mi. </p>

</div><!----End div contact----->

<div id="social">
<h2>Social</h2>
<p>Etiam tincidunt diam dolor, sit amet vestibulum nulla rhoncus at.</p>

</div><!-----End div social------>
	
<div id="pictures">
		<h2>Pictures</h2>
		<p>Etiam tincidunt diam dolor, sit amet vestibulum nulla rhoncus at. Mauris quis purus mi.</p>
</div><!-----End pictures----->
	
	
</div>

Javascript

Get the top positions of the divs minus some px for padding and assign each of them to a variable. The values of these variables will become the scrolling positions when the links in the navigation are clicked.

var teaching = document.getElementById('teaching').offsetTop - 84;
var social = document.getElementById('social').offsetTop - 84;
var contact = document.getElementById('contact').offsetTop - 84;
var biogs = document.getElementById('biog').offsetTop - 104;
var pictures = document.getElementById('pictures').offsetTop - 84;
var links = document.getElementById('links').offsetTop - 84;

Initialise the page at the top and animate to the first content div. Highlight the first element in the nav list by giving it a class of ‘active’ and some associated css.

$('html, body').stop().animate({scrollTop:biogs}, 2000);		
$('#biogs').addClass('active');

The css for my active class looks like this.

ul#nav li.active {color:#EEB78C; font-family: CorbertCondensed-Bold;}

Separate click functions for each navigation element.

			
		$('#socials').click(function(event) {
		event.preventDefault();
			if(!$('html,body').is(':animated')) {
			$('html, body').stop().animate({scrollTop:social}, 2000);
			
			}
		});
		$('#contacts').click(function(event) {
		event.preventDefault();
			if(!$('html, body').is(':animated')) {
			$('html, body').stop().animate({scrollTop:contact}, 2000);
			
			}
		});
		$('#linkss').click(function(event) {
		event.preventDefault();
		if(!$('html, body').is(':animated')) {
			$('html, body').stop().animate({scrollTop:links}, 2000);
			
			}
		});
		$('#picturess').click(function(event) {
		event.preventDefault();
			if(!$('html,body').is(':animated')) {
			$('html, body').stop().animate({scrollTop:pictures}, 2000);
			
			}
		});
		$('#biogs').click(function(event) {
		event.preventDefault();
			if(!$('html,body').is(':animated')) {
			$('html, body').stop().animate({scrollTop:biogs}, 2000);
				
			}
		});
		$('#teachings').click(function(event) {
		event.preventDefault();
			if(!$('html,body').is(':animated')) {
			$('html, body').stop().animate({scrollTop:teaching}, 2000);
				
			}
		});

The final bit of javascript code, which I modified from this post on Stack exchange, firstly makes an array of all the offset().top positions of the content divs, then returns the index of the section being scrolled through using the function getCurrent and finally uses this returned index to change the ‘active’ class of the nav elements according to the scroll position on the page.

var $sections = $('#full').children(); // all the section divs
var $navs = $('#nav li');  // nav links

		var topsArray = $sections.map(function() {
		return $(this).offset().top -120;}).get();                         // Make array of all scrollTop positions of content divs, with 120px padding to change the class a little sooner
		var len = topsArray.length;  // number of total sections
		var currentIndex = 0;        // current section selected
		var getCurrent = function(top) {   
		for( var i = 0; i < len; i++ ) {   // index to be displayed depending on top position
        if(top > topsArray[i] && top < topsArray[i+1]) {
            return i;
			}
			else if(top > topsArray[len - 1]) {
				return len - 1;
				}
		}
		};
		
		
		$(document).scroll(function(e) {
		var scrollTop = $(this).scrollTop();
		var checkIndex = getCurrent(scrollTop);
		
			if( checkIndex !== currentIndex ) {
				currentIndex = checkIndex;
				
				$navs.removeClass('active'); // remove 'active' class from all nav list elements
				$navs.eq( currentIndex ).addClass('active'); // add 'active' class to currentIndex	
			}
		});

Many thanks to user113716 for this last bit of code.

Share this