我正在使用新的position: sticky
(info http://updates.html5rocks.com/2012/08/Stick-your-landings-position-sticky-lands-in-WebKit) 创建类似 iOS 的内容列表。
它运行良好,并且比之前的 JavaScript 替代方案优越得多(example http://jsbin.com/omanut/2/edit)但是据我所知,触发事件时不会触发任何事件,这意味着当栏到达页面顶部时我无法执行任何操作,这与之前的解决方案不同。
我想添加一个类(例如stuck
) 当一个元素带有position: sticky
点击页面顶部。有没有办法用 JavaScript 来监听这个?使用 jQuery 就很好了。
Demo https://codepen.io/vsync/pen/bGbmqZe?editors=0110 with 路口观察者 https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API(使用一个技巧):
// get the sticky element
const stickyElm = document.querySelector('header')
const observer = new IntersectionObserver(
([e]) => e.target.classList.toggle('isSticky', e.intersectionRatio < 1),
{threshold: [1]}
);
observer.observe(stickyElm)
body{ height: 200vh; font:20px Arial; }
section{
background: lightblue;
padding: 2em 1em;
}
header{
position: sticky;
top: -1px; /* ➜ the trick */
padding: 1em;
padding-top: calc(1em + 1px); /* ➜ compensate for the trick */
background: salmon;
transition: .1s;
}
/* styles for when the header is in sticky mode */
header.isSticky{
font-size: .8em;
opacity: .5;
}
<section>Space</section>
<header>Sticky Header</header>
The top
值需要是-1px
或者该元素永远不会与浏览器窗口的顶部相交(因此永远不会触发路口观察者).
为了应对这一点1px
隐藏内容,额外1px
应将足够的空间添加到粘性元素的边框或填充中。
???? 或者,如果您希望保持 CSS 不变(top:0
),然后您可以在路口观察者-level 通过添加设置rootMargin: '-1px 0px 0px 0px'
(as @马特里克在他的回答中显示)
老式的演示scroll
事件监听器:
- 自动检测第一个可滚动父级 https://stackoverflow.com/q/35939886/104380
- 限制滚动事件 https://stackoverflow.com/q/27078285/104380
- 用于关注点分离的功能组合
- 事件回调缓存:
scrollCallback
(需要时可以解除绑定)
// get the sticky element
const stickyElm = document.querySelector('header');
// get the first parent element which is scrollable
const stickyElmScrollableParent = getScrollParent(stickyElm);
// save the original offsetTop. when this changes, it means stickiness has begun.
stickyElm._originalOffsetTop = stickyElm.offsetTop;
// compare previous scrollTop to current one
const detectStickiness = (elm, cb) => () => cb & cb(elm.offsetTop != elm._originalOffsetTop)
// Act if sticky or not
const onSticky = isSticky => {
console.clear()
console.log(isSticky)
stickyElm.classList.toggle('isSticky', isSticky)
}
// bind a scroll event listener on the scrollable parent (whatever it is)
// in this exmaple I am throttling the "scroll" event for performance reasons.
// I also use functional composition to diffrentiate between the detection function and
// the function which acts uppon the detected information (stickiness)
const scrollCallback = throttle(detectStickiness(stickyElm, onSticky), 100)
stickyElmScrollableParent.addEventListener('scroll', scrollCallback)
// OPTIONAL CODE BELOW ///////////////////
// find-first-scrollable-parent
// Credit: https://stackoverflow.com/a/42543908/104380
function getScrollParent(element, includeHidden) {
var style = getComputedStyle(element),
excludeStaticParent = style.position === "absolute",
overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/;
if (style.position !== "fixed")
for (var parent = element; (parent = parent.parentElement); ){
style = getComputedStyle(parent);
if (excludeStaticParent && style.position === "static")
continue;
if (overflowRegex.test(style.overflow + style.overflowY + style.overflowX))
return parent;
}
return window
}
// Throttle
// Credit: https://jsfiddle.net/jonathansampson/m7G64
function throttle (callback, limit) {
var wait = false; // Initially, we're not waiting
return function () { // We return a throttled function
if (!wait) { // If we're not waiting
callback.call(); // Execute users function
wait = true; // Prevent future invocations
setTimeout(function () { // After a period of time
wait = false; // And allow future invocations
}, limit);
}
}
}
header{
position: sticky;
top: 0;
/* not important styles */
background: salmon;
padding: 1em;
transition: .1s;
}
header.isSticky{
/* styles for when the header is in sticky mode */
font-size: .8em;
opacity: .5;
}
/* not important styles*/
body{ height: 200vh; font:20px Arial; }
section{
background: lightblue;
padding: 2em 1em;
}
<section>Space</section>
<header>Sticky Header</header>
这是一个React 组件演示 https://codepen.io/vsync/pen/bGbmqZe?editors=0110它使用第一种技术
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)