得到一个粘贴的头部“推出”,就像 Instagram 的 iPhone 应用程序使用 CSS 和 jQuery 一样

Instagram 应用程序有一个很好的粘贴头部,可以将当前的头部推到新的头部的位置。我找到了一个关于如何在 Android 上实现本地化的很棒的教程,但是我想用 JavaScript 和 CSS 来实现。

我能够让我的头部切换到一个新的,但我似乎无法找到一种方法来模仿 Instagram 的做法。非常感谢您的帮助。

* < em > 编辑:我能够让标题粘在页面的顶部,当滚动使用路径点时,就像 Cj 在评论中指出的那样。(连接到航路点). 我遇到的主要问题是 Instagram 在 iPhone 手机应用程序中使用的“上推”效果。我会链接到一个例子,但我从来没有看到它使用之前。 *

* * 编辑2:通过使用@Chris 提供的部分代码,我能够使标题粘贴起来。然后我加了一个。滑动效应。我现在的问题是。仅当到达下一个头时才会发生 SlideUp 效果。现在该效果在卷轴上激活。

密码如下:

(function() {
function stickyTitles(stickies) {
this.load = function() {
stickies.each(function(){
var thisSticky = jQuery(this);
jQuery.data(thisSticky[0], 'pos', thisSticky.offset().top);
});
}
this.scroll = function() {
stickies.each(function(){
var thisSticky = jQuery(this),
pos = jQuery.data(thisSticky[0], 'pos');
if (pos <= jQuery(window).scrollTop()) {
thisSticky.addClass("fixed");
// added this
$(".followMeBar:parent").slideUp();


} else {
thisSticky.removeClass("fixed");
}
});
}
}
jQuery(document).ready(function(){
var newStickies = new stickyTitles(jQuery(".followMeBar"));
newStickies.load();
jQuery(window).on("scroll", function() {
newStickies.scroll();


});
});

})();

42897 次浏览

这个问题没有一个快速或简单的答案,但通过一点创造性的哄骗,我们可以模仿同样的功能。

我们需要的是一系列的元素,我们可以识别,循环,然后设置,以便当我们到达他们的位置在页面上的前一个项目是推动和新的项目成为固定的。我们需要使用 jQuery 的 offset().top方法检索元素的初始位置,并将其存储在 data标记中,以便以后引用它。剩下的会在我们滚动的时候计算出来。

这应该会奏效:

var stickyHeaders = (function() {


var $window = $(window),
$stickies;


var load = function(stickies) {


if (typeof stickies === "object" && stickies instanceof jQuery && stickies.length > 0) {


$stickies = stickies.each(function() {


var $thisSticky = $(this).wrap('<div class="followWrap" />');
  

$thisSticky
.data('originalPosition', $thisSticky.offset().top)
.data('originalHeight', $thisSticky.outerHeight())
.parent()
.height($thisSticky.outerHeight());
});


$window.off("scroll.stickies").on("scroll.stickies", function() {
_whenScrolling();
});
}
};


var _whenScrolling = function() {


$stickies.each(function(i) {


var $thisSticky = $(this),
$stickyPosition = $thisSticky.data('originalPosition');


if ($stickyPosition <= $window.scrollTop()) {
        

var $nextSticky = $stickies.eq(i + 1),
$nextStickyPosition = $nextSticky.data('originalPosition') - $thisSticky.data('originalHeight');


$thisSticky.addClass("fixed");


if ($nextSticky.length > 0 && $thisSticky.offset().top >= $nextStickyPosition) {


$thisSticky.addClass("absolute").css("top", $nextStickyPosition);
}


} else {
        

var $prevSticky = $stickies.eq(i - 1);


$thisSticky.removeClass("fixed");


if ($prevSticky.length > 0 && $window.scrollTop() <= $thisSticky.data('originalPosition') - $thisSticky.data('originalHeight')) {


$prevSticky.removeClass("absolute").removeAttr("style");
}
}
});
};


return {
load: load
};
})();


$(function() {
stickyHeaders.load($(".followMeBar"));
});
.followMeBar {
background: #999;
padding: 10px 20px;
position: relative;
z-index: 1;
color: #fff;
}
.followMeBar.fixed {
position: fixed;
top: 0;
width: 100%;
box-sizing: border-box;
z-index: 0;
}
.followMeBar.fixed.absolute {
position: absolute;
}
/* For aesthetics only */


body {
margin: 0;
font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="followMeBar">A</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">B</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">C</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">D</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">E</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">F</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">G</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">H</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">I</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">J</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">K</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">L</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">M</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">N</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">O</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">P</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">Q</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">R</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">S</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">T</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">U</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">V</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">W</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">X</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">Y</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<div class="followMeBar">Z</div>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

这是 CSS 唯一的版本:

在你说“什么”之前!当只有 CSS 版本的时候,我刚刚经历了所有这些? !”它只能在几个浏览器中工作。例如,在 firefox 中尝试这样做:

.sticky {
position: -webkit-sticky;
position: -moz-sticky;
position: -o-sticky;
position: -ms-sticky;
position: sticky;
top: 0;
left: 0;
right: 0;
display: block;
z-index: 1;
background: #999;
color: #fff;
padding: 10px 20px;
}


/* For aesthetics only */
body {
margin: 0;
font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
}
<div data-lorem="p">
<span class="sticky">a</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">b</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">c</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">d</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">e</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">f</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">g</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>
<div data-lorem="p">
<span class="sticky">h</span>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</div>

Http://caniuse.com/#feat=css-sticky

我很难让克里斯的答案准确地为我工作,因为所有的粘贴都在一个相对定位的 div (上面有一个标题,在相对 div 之外)-这个问题的答案只是存储。偏移量()。变量中的相对容器 div 的顶部,并从。Css (‘ top’,价值)。 和 Chris 的版本一样,顶部的值是从文档的顶部推开的,这样工作得很好。 当您添加相对 div 时,top 现在从它的顶部向下推,所以相对 div 之上的任何空格都包含在值中,这是您不希望看到的。 希望这能帮到别人。 詹姆斯

首先,感谢“克里斯 · 斯皮特尔斯”给出的出色回答。

我已经创建了一个修改版本,它消除了包装每个粘性元素的需要,因为它只是改变了它们的相对位置,而不是使用固定的位置。

var stickyHeaders = (function() {


var $stickies;


var load = function(stickies, target) {


if (typeof stickies === "object" && stickies instanceof jQuery && stickies.length > 0) {


$stickies = stickies.each(function() {


var $thisSticky = $(this);


$thisSticky
.data('originalPosition', $thisSticky.offset().top)
.data('originalHeight', $thisSticky.outerHeight());
});


target.off("scroll.stickies").on("scroll.stickies", function(event) {
_whenScrolling(event);
});
}
};


var _whenScrolling = function(event) {


var $scrollTop = $(event.currentTarget).scrollTop();


$stickies.each(function(i) {


var $thisSticky = $(this),
$stickyPosition = $thisSticky.data('originalPosition'),
$newPosition,
$nextSticky;


if ($stickyPosition <= $scrollTop) {


$newPosition = Math.max(0, $scrollTop - $stickyPosition);
$nextSticky = $stickies.eq(i + 1);


if($nextSticky.length > 0) {


$newPosition = Math.min($newPosition, ($nextSticky.data('originalPosition') -  $stickyPosition) - $thisSticky.data('originalHeight'));
}


} else {


$newPosition = 0;
}


$thisSticky.css('transform', 'translateY(' + $newPosition + 'px)');


//could just as easily use top instead of transform
//$thisSticky.css('top', $newPosition + 'px');
});
};


return {
load: load
};
})();


$(function() {
stickyHeaders.load($(".followMeBar"), $(window));
});

Css 简化为:

.followMeBar {
background: #999;
padding: 10px 20px;
position: relative;
z-index: 1;
color: #fff;
}


/* For aesthetics only */


body {
margin: 0;
font-family: Segoe, "Segoe UI", "DejaVu Sans", "Trebuchet MS", Verdana, sans-serif;
}

Http://plnkr.co/edit/wk3h40lfbdn1uftdlzgy?p=preview

下面是另一个例子,展示了如何在使用固定标头时使用偏移量:

Http://plnkr.co/edit/8ybqdcikruvkyrxbzncp?p=preview

我尝试了上面提供的解决方案,但是没有一个能够在没有 bug 的情况下完美工作(主要是在滚动和浏览器兼容性方面的 bug)。 刚找到这个 https://github.com/sarahdayan/feedify对我很有用。

解决方案的基本版本:

CSS

.sectionWrapper{
background-color: #1E1E1E;
padding: 10px 20px;
color: #FF7B05;
width: 100%
height: 45px;
min-height: 45px;


margin-top: 30px;
position: relative;
z-index: 10;
}
.sectionHeader{
}
.sectionEmbed {
}
.sectionFixed {
background-color: #1E1E1E;
padding: 10px 20px;
color: #FF7B05;
width: 100%;
height: 45px;


position: fixed;
top: 0;
left: 0;
margin: 0;
}

超文本标示语言

<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12 sectionWrapper sectionEmbed">
<div class="sectionHeader">Headers here</div>
</div>

JQuery

//check doc is ready
$(function() {
$(window).on("scroll.sectionWrapper", function() {
stickSections();
});
});


//function stickSection
function stickSections()
{
//detach the listener
$(window).off("scroll.sectionWrapper");


$scrollPos = $(window).scrollTop();
$currentSticky = null;


$('.sectionWrapper').each(function(){


$(this).children().removeClass('sectionFixed');


if($scrollPos >= ($(this).offset().top - ($(this).height() - $(this).children().height() - 6)) ){
$currentSticky = $(this);
}
else $(this).children().addClass('sectionEmbed');
});


//apply the fixed class to our scrollPos match
if($currentSticky) $currentSticky.children().addClass('sectionFixed');


//reattach the listener
$(window).on("scroll.sectionWrapper", function() {
stickSections();
});
}

例子

Https://codepen.io/zombiesbyte/pen/eyywvo

玩得开心:)

如果 div 上方的内容带有粘贴的标题,那么这种方法并不总是能够很好地工作: Css (’转换’,’翻译 Y (’+ $newPosition + ‘ px)’) ;

但是这条线很管用 //可以很容易地使用 top 而不是转换 Css (‘ top’,$newPosition + ‘ px’) ;

Chris-spittles 提供的解决方案帮了我很大的忙,但是我也想提供一个普通的 Javascript 解决方案。此外,我还添加了一些功能,可以处理最后一个粘性,以防止粘性在其内容区域之后继续固定。

Https://codepen.io/jamigibbs/pen/qzwjby

const StickySubsections = (function(){
let el


return {
elements: function () {
return {
stickies: [...document.querySelectorAll('.followMeBar')]
}
},


init: function () {
el = this.elements()
this.load()
},


load: function () {
this.setupStickyWrap()
window.addEventListener('scroll', () => this.whenScrolling())
},


setupStickyWrap: function(){
el.stickies.forEach((sticky, i) => {
const stickyWrap = this.addWrap(sticky, 'sticky-wrap')
const heightToTop = sticky.getBoundingClientRect().top + window.scrollY
const outerHeight = sticky.offsetHeight


stickyWrap.parentElement.id = `sticky-content-${i}`
sticky.setAttribute('data-originalPosition', heightToTop)
sticky.setAttribute('data-originalHeight', outerHeight)


stickyWrap.style.height = outerHeight + 'px'
})
},


addWrap: function(el, className, wrap = 'div') {
const wrapper = document.createElement(wrap)
wrapper.classList.add(className)
el.parentNode.insertBefore(wrapper, el)
wrapper.appendChild(el)
return wrapper
},


elementExists: function(el){
return typeof(el) != 'undefined' && el != null
},


stickyPosition: function(el){
return el.getAttribute('data-originalPosition')
},


nextStickyPosition: function(current, next){
return next.getAttribute('data-originalPosition') - current.getAttribute('data-originalHeight')
},


scrollingPositionTop: function(el){
return el.getBoundingClientRect().top + window.scrollY
},


offsetTop: function(el){
return el.getBoundingClientRect().top
},


scrollingPositionBottom: function(el){
return el.getBoundingClientRect().bottom + window.scrollY
},


headerPosition: function(){
return window.scrollY
},


bottomSectionHit: function(contentElement, sticky){
const contentSection = document.getElementById(contentElement)
const sectionBottom = contentSection.getBoundingClientRect().bottom + window.scrollY
const stickyPositionScrolling = sticky.getBoundingClientRect().bottom + window.scrollY


return stickyPositionScrolling >= sectionBottom
},


whenScrolling: function() {
el.stickies.forEach((sticky, i) => {
const nextSticky = el.stickies[i + 1]
const prevSticky = el.stickies[i - 1]


if (this.stickyPosition(sticky) <= this.headerPosition()) {
sticky.classList.add('fixed')


if (this.elementExists(nextSticky)) {


while (this.scrollingPositionBottom(sticky) >= this.nextStickyPosition(sticky, nextSticky) + 50) {
sticky.classList.add('absolute')
sticky.style.top = this.nextStickyPosition(sticky, nextSticky)
}


// Handle last sticky element
} else {
if (this.bottomSectionHit(`sticky-content-${i}`, sticky)) {
sticky.classList.remove('fixed')
}
}


} else {


sticky.classList.remove('fixed')


if (this.elementExists(prevSticky) && window.scrollY <= this.stickyPosition(sticky)){
prevSticky.classList.remove('absolute')
prevSticky.removeAttribute('style')
}
}
})
}


}
}())


StickySubsections.init()

一定要用 div包装

注意第6个标题,因为它没有包装在 div

h1, h2{
position: sticky;
top: 0;
}


div{
height: 500px;
}
<div>
<h1>lorem ipsum doloro sit <br> amet 1</h1>
</div>


<div>
<h1>lorem ipsum doloro sit 2</h1>
</div>


<div>
<h2>lorem ipsum doloro sit 3</h2>
</div>


<div>
<h1>lorem ipsum doloro sit <br> amet 4</h1>
</div>


<div>
<h2>lorem ipsum doloro sit <br> amet 5</h2>
</div>


<h2>lorem ipsum doloro sit <br> amet 6</h2>


<div></div>


<div>
<h1>lorem ipsum doloro sit  7</h1>
</div>


<div>
<h1>lorem ipsum doloro sit <br> amet 8</h1>
</div>


<div>
<h1>lorem ipsum doloro sit <br> amet 9</h1>
</div>