Navigation bar that sticks as you scroll, animating a slider which indicates the page section you are currently looking at. Written with SCSS, Javascript, and JQuery.
A Pen by Calvin Chu on CodePen.
<!-- Hero --> | |
<section class="et-hero-tabs"> | |
<h1>STICKY SLIDER NAV</h1> | |
<h3>Sliding content with sticky tab nav</h3> | |
<div class="et-hero-tabs-container"> | |
<a class="et-hero-tab" href="#tab-es6">ES6</a> | |
<a class="et-hero-tab" href="#tab-flexbox">Flexbox</a> | |
<a class="et-hero-tab" href="#tab-react">React</a> | |
<a class="et-hero-tab" href="#tab-angular">Angular</a> | |
<a class="et-hero-tab" href="#tab-other">Other</a> | |
<span class="et-hero-tab-slider"></span> | |
</div> | |
</section> | |
<!-- Main --> | |
<main class="et-main"> | |
<section class="et-slide" id="tab-es6"> | |
<h1>ES6</h1> | |
<h3>something about es6</h3> | |
</section> | |
<section class="et-slide" id="tab-flexbox"> | |
<h1>Flexbox</h1> | |
<h3>something about flexbox</h3> | |
</section> | |
<section class="et-slide" id="tab-react"> | |
<h1>React</h1> | |
<h3>something about react</h3> | |
</section> | |
<section class="et-slide" id="tab-angular"> | |
<h1>Angular</h1> | |
<h3>something about angular</h3> | |
</section> | |
<section class="et-slide" id="tab-other"> | |
<h1>Other</h1> | |
<h3>something about other</h3> | |
</section> | |
</main> |
class StickyNavigation { | |
constructor() { | |
this.currentId = null; | |
this.currentTab = null; | |
this.tabContainerHeight = 70; | |
let self = this; | |
$('.et-hero-tab').click(function() { | |
self.onTabClick(event, $(this)); | |
}); | |
$(window).scroll(() => { this.onScroll(); }); | |
$(window).resize(() => { this.onResize(); }); | |
} | |
onTabClick(event, element) { | |
event.preventDefault(); | |
let scrollTop = $(element.attr('href')).offset().top - this.tabContainerHeight + 1; | |
$('html, body').animate({ scrollTop: scrollTop }, 600); | |
} | |
onScroll() { | |
this.checkTabContainerPosition(); | |
this.findCurrentTabSelector(); | |
} | |
onResize() { | |
if(this.currentId) { | |
this.setSliderCss(); | |
} | |
} | |
checkTabContainerPosition() { | |
let offset = $('.et-hero-tabs').offset().top + $('.et-hero-tabs').height() - this.tabContainerHeight; | |
if($(window).scrollTop() > offset) { | |
$('.et-hero-tabs-container').addClass('et-hero-tabs-container--top'); | |
} | |
else { | |
$('.et-hero-tabs-container').removeClass('et-hero-tabs-container--top'); | |
} | |
} | |
findCurrentTabSelector(element) { | |
let newCurrentId; | |
let newCurrentTab; | |
let self = this; | |
$('.et-hero-tab').each(function() { | |
let id = $(this).attr('href'); | |
let offsetTop = $(id).offset().top - self.tabContainerHeight; | |
let offsetBottom = $(id).offset().top + $(id).height() - self.tabContainerHeight; | |
if($(window).scrollTop() > offsetTop && $(window).scrollTop() < offsetBottom) { | |
newCurrentId = id; | |
newCurrentTab = $(this); | |
} | |
}); | |
if(this.currentId != newCurrentId || this.currentId === null) { | |
this.currentId = newCurrentId; | |
this.currentTab = newCurrentTab; | |
this.setSliderCss(); | |
} | |
} | |
setSliderCss() { | |
let width = 0; | |
let left = 0; | |
if(this.currentTab) { | |
width = this.currentTab.css('width'); | |
left = this.currentTab.offset().left; | |
} | |
$('.et-hero-tab-slider').css('width', width); | |
$('.et-hero-tab-slider').css('left', left); | |
} | |
} | |
new StickyNavigation(); |
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script> |
body { | |
font-family: "Century Gothic", 'Lato', sans-serif; | |
} | |
a { | |
text-decoration: none; | |
} | |
.et-hero-tabs, | |
.et-slide { | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
height: 100vh; | |
position: relative; | |
background: #eee; | |
h1 { | |
font-size: 3rem; | |
margin: 0; | |
letter-spacing: 1rem; | |
} | |
h3 { | |
font-size: 1rem; | |
letter-spacing: 0.3rem; | |
opacity: 0.6; | |
} | |
} | |
.et-hero-tabs-container { | |
display: flex; | |
flex-direction: row; | |
position: absolute; | |
bottom: 0; | |
width: 100%; | |
height: 70px; | |
box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); | |
background: #fff; | |
z-index: 10; | |
&--top { | |
position: fixed; | |
top: 0; | |
} | |
} | |
.et-hero-tab { | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
flex: 1; | |
color: #000; | |
letter-spacing: 0.1rem; | |
transition: all 0.5s ease; | |
&:hover { | |
color:white; | |
background: rgba(102,177,241,0.8); | |
transition: all 0.5s ease; | |
} | |
} | |
.et-hero-tab-slider { | |
position: absolute; | |
bottom: 0; | |
width: 0; | |
height: 6px; | |
background: #66B1F1; | |
transition: left 0.3s ease; | |
} |