当元素卡住时,我需要为其应用 CSS 类position:sticky
。当我使用顶部位置时,这个方法可以正常工作,但我无法确定底部位置的 CSS 类。我想我需要在某个地方考虑高度,但我不知道这里最好的做法是什么。
我还需要它与偏移配合使用,只需顶部或底部的位置即可0
。这是我目前所拥有的
const stickyElements = [...document.querySelectorAll(".sticky")];
window.addEventListener("scroll", () => {
stickyElements.forEach((el) => toggleClassIfStuck(el))
});
window.dispatchEvent(new Event('scroll')); //trigger initially
function toggleClassIfStuck(el){
const computedStyles = getComputedStyle(el);
if (this.canBeStuck(computedStyles)) {
const hasTopPositionSet = computedStyles.top !== 'auto';
const hasBottomPositionSet = computedStyles.bottom !== 'auto';
if (hasTopPositionSet || hasBottomPositionSet) {
el.classList.toggle('is-stuck', this.isStuck(el, computedStyles, hasBottomPositionSet))
}
}
}
function canBeStuck(computedStyles) {
return computedStyles.display !== 'none' && computedStyles.position === 'sticky';
}
function isStuck(el, computedStyles, shouldUseBottomPosition) {
const offsetParent = el.offsetParent; //the element which this element is relatively sticky to
const rect = el.getBoundingClientRect();
const parentRect = offsetParent.getBoundingClientRect();
if (shouldUseBottomPosition) {
//this isn't correct, but not sure what to check here!
const elBottom = parseInt(computedStyles.bottom, 10);
return rect.top - rect.bottom === elBottom;
} else {
const elTop = parseInt(computedStyles.top,10);
return rect.top === elTop;
}
}
.sticky {
position:sticky;
background: #EEE;
padding: .5rem;
border: 1px solid #DDD;
transition: all 200ms;
}
.sticky-top { top:0; }
.sticky-top-offset { top: 1rem;}
.sticky-bottom { bottom: 0; }
.sticky-bottom-offset { bottom: 1rem; }
.is-stuck{
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.25);
background: lightskyblue;
}
main{ display: flex; gap:.5rem;}
section{ height:120vh; width: 40%; }
<main>
<section>
<br>
<div id="one" class="sticky sticky-top">Top</div>
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
<div class="sticky sticky-bottom">Bottom</div>
<br>
</section>
<section>
<br><br><br><br>
<div class="sticky sticky-top-offset">Top with offset</div>
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br>
<div class="sticky sticky-bottom-offset">Bottom with offset</div>
<br><br><br><br>
</section>
</main>