JSFiddle - React, Tailwind, and code Playground

by Wendigooor

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.js"></script>
<script src="https://code.angularjs.org/angular-1.0.1.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.js"></script>
<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <div class="sections" scroll>
            <section class="section" ng-repeat="section in sections" ng-include="'section.html'">           
            </section>
        </div>
    </div>
    
    <script type="text/ng-template" id="section.html">
        <header class="section-header">
             <h1 class="section-heading">{{section.title}}</h1>
        </header>
        <div class="section-content">{{section.content}}</div>
    </script>
<div>

SCSS

$color1: change-color(#6B45C9, $lightness: 58%);
$color2: change-color(#ED5C5A, $lightness: 58%);

*, *:before, *:after {
    box-sizing: border-box;
}

@mixin section-colors($color) {
    background: change-color($color, $lightness: 70%);
    .section-header {
        width: 100%;
        color: white;
        background: change-color($color, $lightness: 45%);
        border-bottom-color: rgba(black, .1);
    }
    .section-content {
        color: change-color($color, $lightness: 12%);
    }
}

.section {
    min-height: 200px;
    @include section-colors($color1);
    &:nth-child(even) {
       @include section-colors($color2);
    }
    .section-header {
        border-bottom-width: 1px;
        border-bottom-style: solid;
        padding: 6px 12px;
    }
    .section-heading {
        font-size: 18px;
        line-height: 24px;
    }
    .section-content {
        padding: 12px;
    }
}

JavaScript

var myApp = angular.module('myApp', []);

myApp.controller("MyCtrl", function MyCtrl($scope) {
    $scope.sections = [];
    for (var i = 0; i < 10; i++) {
        $scope.sections.push({
            title: "Section " + (i + 1),
            content: "Some content. Lorem ipsum dolor sit amet."
        });
    }

    $scope.lastHeaderTopValue = 0;
    $scope.globalCount = 0;
    $scope.sectionsHeaders = [];
})

.directive("scroll", function ($window) {
    return function (scope, element, attrs) {
        angular.element($window).bind("scroll", function () {
            count = 0;
            headers = $('.section-header')
            headerHeight = 36 // $(headers[0]).height()
            pageOffset = this.pageYOffset + headerHeight * scope.globalCount

            headers.each(function (index, el) {
                if ($(el).offset().top <= pageOffset) {
                    count += 1;
                }
                scope.sectionsHeaders[index] = $(el).offset().top + index * headerHeight
            })
            Object.freeze(scope.sectionsHeaders)

            scope.lastHeaderTopValue = scope.sectionsHeaders[scope.globalCount]

            if (count > 1 && count <= scope.globalCount) {
                if (pageOffset + headerHeight * (scope.globalCount - 2) < scope.sectionsHeaders[scope.globalCount - 1]) {
                    count -= 1
                    scope.globalCount = -1
                }
            }
            scope.globalCount = Math.max(count, scope.globalCount)

            headers.each(function (index, el) {
                if (index < scope.globalCount) {
                    $(el).css('top', (index) * headerHeight)
                    $(el).css('position', 'fixed')
                } else {
                    $(el).removeAttr('style');
                }
            })
            if (scope.globalCount == 1 && $(headers[0]).offset().top == 0) {
                $(headers[0]).removeAttr('style');
            }
        });
    };
})