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;
        }
    });
});