Ale*_*ust 33 html javascript css jquery position
我正在使用新的position: sticky(info)来创建类似iOS的内容列表.
它运行良好,远远优于之前的JavaScript替代方案(例子),但据我所知,当触发事件时不会触发任何事件,这意味着当条形图到达页面顶部时我无法执行任何操作,与以前不同解.
stuck当一个元素position: sticky点击页面顶部时,我想添加一个类(例如).有没有办法用JavaScript来听这个?使用jQuery很好.
position: sticky可以在此处找到新使用的演示.
mat*_*ick 26
我找到了一个与@vsync 的答案有些相似的解决方案,但它不需要您需要添加到样式表中的“hack”。您可以简单地更改 IntersectionObserver 的边界以避免需要将元素本身移动到视口之外:
const observer = new IntersectionObserver(callback, {
rootMargin: '-1px 0px 0px 0px',
threshold: [1],
});
observer.observe(element);
Run Code Online (Sandbox Code Playgroud)
Sco*_*ard 14
如果有人通过Google来到这里,他们自己的工程师之一就可以使用IntersectionObserver,自定义事件和标记来解决问题:
https://developers.google.com/web/updates/2017/09/sticky-headers
// 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)Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
<section>Space</section>
<header>Sticky Header</header>Run Code Online (Sandbox Code Playgroud)
该top值必须为,-1px否则该元素将永远不会与浏览器窗口的顶部相交(因此永远不会触发相交观察器)。
为了解决1px隐藏内容的问题,1px应在边框或粘贴元素的填充处添加额外的空间。
scroll事件监听器的演示: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);
}
}
}Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
<section>Space</section>
<header>Sticky Header</header>Run Code Online (Sandbox Code Playgroud)
目前没有原生解决方案.请参阅定位位置:当前处于"卡住"状态的粘性元素.但是,我有一个CoffeeScript解决方案,可以与本机position: sticky和polyfill一起使用,实现粘性行为.
将"粘性"类添加到要粘贴的元素:
.sticky {
position: -webkit-sticky;
position: -moz-sticky;
position: -ms-sticky;
position: -o-sticky;
position: sticky;
top: 0px;
z-index: 1;
}
Run Code Online (Sandbox Code Playgroud)
CoffeeScript用于监控"粘性"元素位置,并在处于"粘性"状态时添加"卡住"类:
$ -> new StickyMonitor
class StickyMonitor
SCROLL_ACTION_DELAY: 50
constructor: ->
$(window).scroll @scroll_handler if $('.sticky').length > 0
scroll_handler: =>
@scroll_timer ||= setTimeout(@scroll_handler_throttled, @SCROLL_ACTION_DELAY)
scroll_handler_throttled: =>
@scroll_timer = null
@toggle_stuck_state_for_sticky_elements()
toggle_stuck_state_for_sticky_elements: =>
$('.sticky').each ->
$(this).toggleClass('stuck', this.getBoundingClientRect().top - parseInt($(this).css('top')) <= 1)
Run Code Online (Sandbox Code Playgroud)
注意:此代码仅适用于垂直粘性位置.
添加 Chrome 后position: sticky,发现它还不够准备,并被降级为 --enable-experimental-webkit-features 标志。保罗·爱尔兰 (Paul Irish)在二月份表示,“atm 功能处于一种奇怪的边缘状态”。
我一直在使用Polyfill,直到它变得令人头疼。它工作得很好,但也有一些极端情况,比如 CORS 问题,并且它会通过对所有 CSS 链接执行 XHR 请求并重新解析浏览器忽略的“position:sticky”声明来减慢页面加载速度。
现在我使用ScrollToFixed,我比StickyJS更喜欢它,因为它不会用包装器弄乱我的布局。
| 归档时间: |
|
| 查看次数: |
14965 次 |
| 最近记录: |