我需要检测粘性元素何时被固定/粘住。
如果当时只有一个粘性元素,那么使用这种方法可以正常工作。 请注意,技巧是设置top: -1px
并检查元素是否离开视口
const stickyElements = document.querySelectorAll('.sticky-element');
const observer = new IntersectionObserver(
([entry]) => {
entry.target.classList.toggle('pinned', entry.intersectionRatio < 1);
},
{ threshold: [1, 0.01] },
);
stickyElements.forEach((sticky, i) => {
if (sticky) {
observer.observe(sticky);
}
});
.sticky-element {
position: sticky;
top: -1px;
z-index: 2;
}
.sticky-element.pinned {
background: white;
border-bottom: 1px solid #ccc;
}
.sticky-element.pinned {
&:after {
content: ' (pinned)';
}
}
.just-content {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #f8f8f8;
}
<div class="sticky-element">I'm sticky</div>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky 1</div>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky 2</div>
<div class="just-content">I'm just normal element</div>
const stickyElements = document.querySelectorAll('.sticky-element');
const observer = new IntersectionObserver(
([entry]) => {
entry.target.classList.toggle('pinned', entry.intersectionRatio < 1);
}, {
threshold: [1, 0.01]
},
);
stickyElements.forEach((sticky, i) => {
if (sticky) {
observer.observe(sticky);
}
});
.sticky-nav {
position: sticky;
top: -1px;
z-index: 2;
outline: 1px dashed black;
}
.sticky-element {
position: sticky;
top: 15px;
z-index: 2;
outline: 1px dashed orange;
}
.sticky-element.pinned {
background: white;
border-bottom: 1px solid #ccc;
}
.sticky-element.pinned {
&:after {
content: ' (pinned)';
}
}
.just-content {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #f8f8f8;
}
<div class="just-content">I'm just normal element</div>
<nav class="sticky-nav">Sticky element just above</nav>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky</div>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky 1</div>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky 2</div>
<div class="just-content">I'm just normal element</div>
所以观察者在这种情况下不起作用,因为我猜该项目实际上并没有离开视口。
所以问题是,这种情况有什么解决方法吗?也许基于容器?
我能够通过将
const stickyElements = document.querySelectorAll('.sticky-element');
const onScroll = () => {
requestAnimationFrame(() => {
stickyElements.forEach((sticky) => {
if (sticky) {
const elementCSSTop = parseInt(window.getComputedStyle(sticky, null).getPropertyValue('top'));
sticky.classList.toggle('pinned', sticky.getBoundingClientRect().top === elementCSSTop);
}
});
});
};
window.addEventListener('scroll', onScroll);
.sticky-nav {
position: sticky;
top: -1px;
z-index: 2;
outline: 1px dashed black;
}
.sticky-element {
position: sticky;
top: 18px;
z-index: 2;
}
.sticky-element.pinned {
background: white;
border-bottom: 1px solid #ccc;
}
.sticky-element.pinned {
&:after {
content: ' (pinned)';
}
}
.just-content {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #f8f8f8;
}
<div class="just-content">I'm just normal element</div>
<nav class="sticky-nav">Sticky element just above</nav>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky</div>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky 1</div>
<div class="just-content">I'm just normal element</div>
<div class="sticky-element">I'm sticky 2</div>
<div class="just-content">I'm just normal element</div>