JSFiddle - React, Tailwind, and code Playground
by gunderson
HTML
<div class="sidebar"><h2>About us</h2>
<h3><a href="#chapter1" class="link active" id="chapter1">Chapter 1</a></h3>
<h3><a href="#chapter2" class="link" id="chapter2">Chapter 2</a></h3>
<h3><a href="#chapter3" class="link" id="chapter3">Chapter 3</a></h3>
</div>
<div class='main'>
<section id="chapter1">
<a id="chapter1"></a>
</section>
<section id="chapter2">
<a id="chapter2"></a>
</section>
<section id="chapter3">
<a id="chapter3"></a>
</section>
</div>
CSS
* {
box-sizing: border-box;
}
html, body{
height: 100%;
margin: 0;
padding:0;
}
.sidebar{
float: left;
width: 20%;
height: 100%;
padding: 15px;
}
a.link.active{
background: #888;
}
.main{
float: left;
width: 80%;
height: 100%;
overflow: scroll;
}
section{
height: 200%;
}
section#chapter1{
background: #f00;
}
section#chapter2{
background: #00f;
}
section#chapter3{
background: #0f0;
}
JavaScript
$(".main").on("scroll",function(e){
var fifty_percent_y = $(".main").height() * 0.5;
var scroll_position = $(this).scrollTop();
var prev_scroll_position = $(this).data('scroll_position');
var delta = scroll_position - prev_scroll_position;
$(this).data('scroll_position', scroll_position);
//the rule is: if the top of chapter section tag crosses up across 50% then it becomes active, or if the bottom of a section tag crosses down across 50% then it becomes active.
$('section').each(function(i, el){
$this = $(this);
var top_y = $this.position().top;
var bottom_y = top_y + $this.height();
var top_percentage = top_y / $this.parent().height();
var play_percentage = (top_percentage > 0) ? top_percentage : top_y / $this.height();
if ((top_y < fifty_percent_y && top_y + delta > fifty_percent_y) ||
(bottom_y > fifty_percent_y && bottom_y + delta < fifty_percent_y)
){
$("a").removeClass('active');
$("a#" + $this[0].id).addClass('active');
return false;
}
});
});