The need for position: sticky
was around for years before it was implemented natively, and I can boast that I implemented it with JavaScript and scroll
events for ages. Eventually we got position: sticky
, and it works well from a visual perspective, but I wondered how can we determine when the element actually became pinned due to scroll.
We can determine if an element has become sticky thanks to the IntersectionObserver API!
Pinning an element to the top of its container is as easy as one CSS directive:
.myElement { position: sticky; }
The question still remains about how we can detect an element being pinned. Ideally there would be a :stuck
CSS directive we could use, but instead the best we can do is applying a CSS class when the element becomes sticky using a CSS trick and some JavaScript magic:
.myElement { position: sticky; /* use "top" to provide threshold for hitting top of parent */ top: -1px; } .is-pinned { color: red; }
const el = document.querySelector(".myElement") const observer = new IntersectionObserver( ([e]) => e.target.classList.toggle("is-pinned", e.intersectionRatioAs soon as
myElement
becomes stuck or unstuck, theis-pinned
class is applied or removed. Check out this demo:See the Pen WNwVXKx by David Walsh (@darkwing) on CodePen.
While there's not too much JavaScript involved, I hope we eventually get a CSS pseudo-class for this. Something like
:sticky
,:stuck
, or:pinned
seems as reasonable as:hover
and:focus
do.