粘性标题 - 使用标签滚动
Posted
技术标签:
【中文标题】粘性标题 - 使用标签滚动【英文标题】:Sticky Header - Scroll with Tabs 【发布时间】:2019-07-27 19:30:05 【问题描述】:我的粘性标题的行为有问题。
期望的行为:
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();
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>
【问题讨论】:
可以包含任何额外的库吗?或者您正在寻找仅 jquery 作为唯一依赖项的答案? 【参考方案1】:您的部分滚动到顶部的原因是由于添加和 去除粘性元素。使用 wrapper 代替 sticky 以始终占据 粘性元素,不管它是否存在。
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>
【讨论】:
谢谢穆尼姆。您的解决方案效果很好,但我在 Firefox 中进行测试时收到错误消息。 "message": "ReferenceError: event is not defined", "filename": "stacksnippets.net/js", "lineno": 115, "colno": 7 现在可以使用了。选项卡单击事件处理程序缺少事件参数。以上是关于粘性标题 - 使用标签滚动的主要内容,如果未能解决你的问题,请参考以下文章