[英]Sticky Header - Scroll with Tabs
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. a)滚动到.nav
底部到达section
顶部的位置将active
类添加到选项卡,它将保持active
直到.nav
到达下一部分的顶部。b) Clicking a corresponding section's
.tab
always navigates you to the top of that section and adds theactive
class to the tab. b)单击相应部分的.tab
始终导航到该部分的顶部,并将active
类添加到选项卡。
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. 因此,无论是通过滚动还是单击,都会始终保持选项卡的active
状态,直到.nav
进入下section
,在这种情况下, active
状态将转到该部分的选项卡等。
Test the issues: 测试问题:
1) Half-way scrolling down Option Two
the active
state of that .tab
is lost. 1)中途向下滚动Option Two
该.tab
的active
状态丢失。
2) The use of scrollTop
is scrolling to the top of the .container
instead of the top of the selected section
. 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();
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>
The reason your section scrolls to the top is the change of positions due to adding and removal sticky element. 您的部分滚动到顶部的原因是由于添加和删除粘性元素而导致的位置更改。 Use a wrapper in place of sticky to always occupy the height of the sticky element whether it is there or not. 使用包装代替粘性以始终占据粘性元素的高度,无论它是否存在。
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(); });
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; }
<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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.