简体   繁体   English

粘滞标题 - 滚动标签

[英]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 a section adds the active class to the tab and it remains active 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 the active 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.tabactive状态丢失。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM