You can use an inViewport jQuery plugin
and create something like this:
/**
* inViewport jQuery plugin by Roko C.B. stackoverflow.com/questions/24768795/
*
* Returns a callback function with an argument holding
* the current amount of px an element is visible in viewport
* (The min returned value is 0 (element outside of viewport)
* The max returned value is the element height + borders)
*/
;(function($, win) {
$.fn.inViewport = function(cb) {
return this.each(function(i,el) {
function visPx(){
var elH = $(el).outerHeight(),
H = $(win).height(),
r = el.getBoundingClientRect(), t=r.top, b=r.bottom;
return cb.call(el, Math.max(0, t>0? Math.min(elH, H-t) : (b<H?b:H)));
}
visPx();
$(win).on("resize scroll", visPx);
});
};
}(jQuery, window));
// let's use it!
$aLinks = $("ul a");
$("[id^=art]").inViewport(function(px){
if(px){
$aLinks.removeClass("active");
$("a[href=#"+ this.id +"]").addClass("active");
}
});
*{margin:0;padding:0;}
p{height:2000px;}
h1{
padding:60px 0;
}
ul{
position:fixed;
width:100%;
}
ul li{
display:inline-block;
}
ul li a{
padding:15px 10px;
display:inlin-block;
transition:0.3s;
}
.active{
background:gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li><a href="#art1">Article 1</a></li>
<li><a href="#art2">Article 2</a></li>
<li><a href="#art3">Article 3</a></li>
<li><a href="#art4">Article 4</a></li>
</ul>
<section id="art1">
<h1>Article 1</h1>
<p>Article content 1</p>
</section >
<section id="art2">
<h1>Article 2</h1>
<p>Article content</p>
</section >
<section id="art3">
<h1>Article 3</h1>
<p>Article content</p>
</section >
<section id="art4">
<h1>Article 4</h1>
<p>Article content</p>
</section >
The principle is to use Link Anchors in your havigation <a href="#page1">
elements and assign the same ID to the page sections <section id="page1">
now both clicking or scrolling the page will add an .active
class to the anchor which section is visible on screen.