Kyl*_*ill 5 html javascript jquery sticky nav
我在粘贴标头的行为方面遇到问题。
所需行为:
a)滚动到
.nav击中底部的位置,section将active类添加到选项卡,并保留active到.nav下一节的顶部。b)单击相应部分
.tab始终会导航到该部分的顶部,并将active该类添加到选项卡。
因此,通过滚动或单击,active选项卡的状态始终保持不变,直到.nav与下一个交叉为止section,在这种情况下,active状态将转到该部分的选项卡,依此类推。
测试问题:
1)中途滚动会丢失Option Two该active状态.tab。
2)使用scrollTop滚动到的顶部,.container而不是选定的顶部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();Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
您的部分滚动到顶部的原因是由于添加和删除粘性元素而导致的位置变化。使用包装器代替粘性元素,无论粘性元素是否存在,都始终占据粘性元素的高度。
class StickyNavigation {
constructor() {
this.currentId = null;
this.currentTab = null;
this.setup();
this.onResize();
let self = this;
$(".tab").click(function(event) {
self.onTabClick(event, $(this));
});
$(".container").scroll(() => {
this.onScroll();
});
$(window).resize(() => {
this.onResize();
});
}
setup() {
this.$sticky = $('.sticky');
window.stk = this.$sticky;
this.$stickyWrap = $('<div>').insertAfter(this.$sticky);
this.$sticky.appendTo(this.$stickyWrap);
}
/*Scrolls down to Tab selection*/
onTabClick(event, element) {
event.preventDefault();
let $targetElement = $(element.attr("href"));
let positionTop = $targetElement.position().top;
let scrollTop = $('.container').scrollTop();
$(".container").animate({
scrollTop: scrollTop - this.stickyOuterHeight + positionTop
}, 600);
}
onScroll() {
this.navPosition();
this.tabAnimation();
}
onResize() {
this.stickyOuterHeight = this.$sticky.outerHeight();
this.$sticky.width(this.$stickyWrap.width());
this.$stickyWrap.css('minHeight', this.stickyOuterHeight);
}
navPosition() {
if (this.$stickyWrap.position().top < 0) {
this.$sticky.addClass("fixed");
} else {
this.$sticky.removeClass("fixed");
}
}
tabAnimation() {
let desiredSpace = this.stickyOuterHeight + 10;
$("section").each(function() {
let actual = $(this),
actualHeight = actual.height(),
actualAnchor = $(".sticky").find('a[href="#' + actual.attr("id") + '"]');
let actualTop = actual.position().top;
let actualBottom = actualTop + actualHeight;
if (actualTop < desiredSpace && actualBottom > desiredSpace) {
actualAnchor.addClass("active");
} else {
actualAnchor.removeClass("active");
}
});
}
}
$(function() {
new StickyNavigation();
});Run Code Online (Sandbox Code Playgroud)
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;
}
.sticky {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.sticky.fixed {
position: fixed;
top: 83px;
}
.tab {
padding: 30px 45px;
position: relative;
}
.tab.active {
background: #6567c5;
color: white;
}Run Code Online (Sandbox Code Playgroud)
<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">
Content One
</section>
<section class="long" id="Two">
Content Two
</section>
</div>
</div>Run Code Online (Sandbox Code Playgroud)