JSFiddle - React, Tailwind, and code Playground
by Ayri Rin
HTML
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<nav>
<div class="wrapper">
<div class="nodes">
<div class="line">
<div class="blue">
<div class="red-container">
<div class="red"></div>
</div>
</div>
</div>
<div class="node">
<div class="active-circle">
<div class="splash"></div>
<div class="cover">
<div class="white"></div>
</div>
</div>
<div class="inactive-circle">
<div class="small-cover">
</div>
</div>
</div>
<div class="node">
<div class="active-circle">
<div class="splash"></div>
<div class="cover">
<div class="white"></div>
</div>
</div>
<div class="inactive-circle">
<div class="small-cover">
</div>
</div>
</div>
<div class="node">
<div class="active-circle">
<div class="splash"></div>
<div class="cover">
<div class="white"></div>
</div>
</div>
<div class="inactive-circle">
<div class="small-cover">
</div>
</div>
</div>
<div class="node">
<div class="active-circle">
<div class="splash"></div>
<div class="cover">
<div class="white"></div>
</div>
</div>
<div class="inactive-circle">
<div class="small-cover">
</div>
</div>
</div>
<div class="node">
<div class="active-circle">
<div class="splash"></div>
<div class="cover">
<div class="white"></div>
</div>
</div>
<div class="inactive-circle">
<div class="small-cover">
...
CSS
@import url(https://fonts.googleapis.com/css?family=Squada+One);
* {
box-sizing: border-box;
}
body {
background: #000;
padding: 0px;
margin: 0px;
}
nav {
background: rgba(0, 0, 0, 0.8);
padding: 18px;
position: fixed;
bottom: 50px;
height: 55px;
left: 50%;
width: 800px;
margin-left: -400px;
z-index: 3;
}
nav .wrapper {
padding: 0;
width: 785px;
}
nav .wrapper, nav svg {
height: 100%;
}
nav svg {
margin-right: 15px;
cursor: pointer;
height: 20px;
width: 30px;
float: left;
}
nav svg path, nav svg rect {
fill: #fff;
}
nav .nodes {
position: relative;
margin-top: -5px;
margin-left: 5px;
float: left;
}
.line {
position: absolute;
width: 705px;
height: 1px;
top: 14px;
}
.line .red, .line .blue {
width: 100%;
height: 1px;
}
.line .red-container {
overflow: hidden;
height: 1px;
width: 58px;
}
.line .red {
background-color: #4b1202;
*zoom: 1;
filter: progid:DXImageTransform.Microsoft.gradient(gradientType=1, startColorstr='#FF4B1202', endColorstr='#FFFD8107');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuMCIgeTE9IjAuNSIgeDI9IjEuMCIgeTI9IjAuNSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZkODEwNyIvPjxzdG9wIG9mZnNldD0iMTYlIiBzdG9wLWNvbG9yPSIjZmQ4MTA3Ii8+PHN0b3Agb2Zmc2V0PSI1OCUiIHN0b3AtY29sb3I9IiNlMDNhMGQiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZDgxMDciLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2dyYWQpIiAvPjwvc3ZnPiA=');
background-size: 100%;
background-image: -webkit-gradient(linear, 0% 50%, 100% 50%, color-stop(0%, #fd8107), color-stop(16%, #fd8107), color-stop(58%, #e03a0d), color-stop(100%, #fd8107));
background-image: -moz-linear-gradient(left, #fd8107 0%, #fd8107 16%, #e03a0d 58%, #fd8107...
JavaScript
$( '.links-item' ).height( window.innerHeight );
var $document = $( document.body );
var $revealBar = $( '.red-container' );
var wrapperHeight = $document.height();
var stepDistance = 101;
var documentHeight = window.innerHeight;
var positions = [];
var heights = [];
var elements = $( '.links-item:not(".main")' );
// Cache heights and positions
for( var i = 0; i < elements.length; i++ ) {
var $element = $(elements[i]);
var height = $element.offset().top + documentHeight;
if (height > wrapperHeight) {
height = wrapperHeight;
}
positions.push(height);
heights.push($element.height());
}
var $nodes = $( '.node' );
// Should totally be debounced /w animation frame. I know,
// this whole thing is slightly inefficient.
// And magic numbers too!
$( document ).scroll( function() {
nodeTop = $document.scrollTop() + documentHeight + 1;
var current = 0;
// Active/non active states
for( var i = 0; i < positions.length; i++ ) {
if(nodeTop > positions[i]) {
current = i;
$nodes.eq( i ).addClass( 'active' );
} else {
$nodes.eq( i ).removeClass( 'active' );
}
}
// Bar positioning, so sections can have different heights.
var distanceToNext = 0;
// Initial node, already has some of the bar filled.
if( nodeTop < positions[0] ) {
var nextStep = (nodeTop - positions[current]) / (positions[current + 1] - positions[current]);
// Calculating for node widths.
var totalWidth = ((stepDistance) + ( current * stepDistance ) + (nextStep * stepDistance)) * 0.4;
$revealBar.width( (0.6 * stepDistance) + totalWidth );
// Final node covered.
} else if (nodeTop > positions[6]) {
$revealBar.width(stepDistance * (current + 1));
// regular nodes
} else if ( current < elements.length ) {
var nextStep = (nodeTop - positions[current]) / (positions[current + 1] - positions[current]);
var totalWidth = stepDistance + ( current * stepDistance ) + (nextStep * stepDistance);
...