I am having problems with the behavior of my sticky header.
Desired behavior:
a) Scrolling to where the bottom of the
.nav
hits the top of asection
adds theactive
class to the tab and it remainsactive
until the.nav
reaches the top of the next section.b) Clicking a corresponding section's
.tab
always navigates you to the top of that section and adds theactive
class to the tab.
So either by scrolling or clicking, the active
state of the tabs is always kept until the .nav
crosses into the next section
, in which case the active
state goes to that section's tab, etc.
Test the issues:
1) Half-way scrolling down Option Two
the active
state of that .tab
is lost.
2) The use of scrollTop
is scrolling to the top of the .container
instead of the top of the selected section
.
class StickyNavigation {
constructor() {
this.currentId = null;
this.currentTab = null;
let self = this;
$(".tab").click(function() {
self.onTabClick(event, $(this));
});
$(".container").scroll(() => {
this.onScroll();
});
$(".container").resize(() => {
this.onResize();
});
}
/*Scrolls down to Tab selection*/
onTabClick(event, element) {
event.preventDefault();
let scrollTop = $(element.attr("href")).offset().top;
if (!$(".nav").hasClass("nav--top")) {
scrollTop = scrollTop;
}
$(".container").animate({
scrollTop: scrollTop
}, 600);
}
onScroll() {
this.navPosition();
this.tabAnimation();
}
navPosition() {
let offset = $(".sticky").offset().top + $(".sticky").height();
if ($(".container").scrollTop() > offset) {
$(".nav").addClass("nav--top");
} else {
$(".nav").removeClass("nav--top");
}
}
tabAnimation() {
$("section").each(function() {
var actual = $(this),
actualHeight = actual.height(),
actualAnchor = $(".sticky").find('a[href="#' + actual.attr("id") + '"]');
if (
actual.offset().top <= $(".container").scrollTop() &&
actual.offset().top + actualHeight > $(".container").scrollTop()
) {
actualAnchor.addClass("active");
} else {
actualAnchor.removeClass("active");
}
});
}
}
new StickyNavigation();
body {
position: fixed;
display: flex;
flex-direction: column;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow: hidden;
}
section {
height: 600px;
border: 2px solid white;
background: blue;
}
section:nth-child(2) {
background: red;
}
.container {
flex: 1;
display: flex;
position: relative;
flex-direction: column;
overflow: auto;
}
.long {
height: 1200px;
}
.header {
height: 75px;
background: green;
}
.hero {
background: silver;
flex: 0;
border: 1px solid;
}
.nav {
background: white;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.nav--top {
position: fixed;
top: 75px;
}
.sticky {
background: white;
display: flex;
flex-direction: row;
flex-wrap: wrap;
position: relative;
}
.tab {
padding: 30px 45px;
position: relative;
}
.tab.active {
background: #6567c5;
color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="header">
<h1>Header</h1>
</div>
<div class="container">
<div class="hero">
<h1>Hero</h1>
</div>
<div class="sticky">
<nav role="navigation" class="nav">
<a class="tab" href="#One">Option One</a>
<a class="tab" href="#Two">Option Two</a>
</nav>
</div>
<div class="main">
<section id="One">
</section>
<section class="long" id="Two">
</section>
</div>
</div>
</div>