Targeting Position:Sticky Elements That Are Currently in a 'Stuck' State

Targeting position:sticky elements that are currently in a 'stuck' state

There is currently no selector that is being proposed for elements that are currently 'stuck'. The Postioned Layout module where position: sticky is defined does not mention any such selector either.

Feature requests for CSS can be posted to the www-style mailing list. I believe a :stuck pseudo-class makes more sense than a ::stuck pseudo-element, since you're looking to target the elements themselves while they are in that state. In fact, a :stuck pseudo-class was discussed some time ago; the main complication, it was found, is one that plagues just about any proposed selector that attempts to match based on a rendered or computed style: circular dependencies.

In the case of a :stuck pseudo-class, the simplest case of circularity would occur with the following CSS:

:stuck { position: static; /* Or anything other than sticky/fixed */ }
:not(:stuck) { position: sticky; /* Or fixed */ }

And there could be many more edge cases that would be difficult to address.

While it's generally agreed upon that having selectors that match based on certain layout states would be nice, unfortunately major limitations exist that make these non-trivial to implement. I wouldn't hold my breath for a pure CSS solution to this problem anytime soon.

Check if DIV is sticky

I've come up with a fairly good solution that can work with any top/bottom offset. Just give it which elements to look for and it can determine if the stickiness threshold has been met or not.

Scroll/resize events can be a bit too frequent, so if that's an issue for you just use the commented out version below with a debounce to check less often.

Note that this assumes your top/bottom CSS values will be in pixels, other units might not work here.

$(() => {  const stuckClass = 'is-stuck';  const $stickyTopElements = $('.sticky-top');  const $stickyBottomElements = $('.sticky-bottom');
const determineSticky = () => { $stickyTopElements.each((i, el) => { const $el = $(el); const stickPoint = parseInt($el.css('top'), 10); const currTop = el.getBoundingClientRect().top; const isStuck = currTop <= stickPoint; $el.toggleClass(stuckClass, isStuck); });
$stickyBottomElements.each((i, el) => { const $el = $(el); const stickPoint = parseInt($el.css('bottom'), 10); const currBottom = el.getBoundingClientRect().bottom; const isStuck = currBottom + stickPoint >= window.innerHeight; $el.toggleClass(stuckClass, isStuck); }); };
//run immediately determineSticky();
//Run when the browser is resized or scrolled //Uncomment below to run less frequently with a debounce //let debounce = null; $(window).on('resize scroll', () => { //clearTimeout(debounce); //debounce = setTimeout(determineSticky, 100);
determineSticky(); });
});
.sticky-top,.sticky-bottom {  position: sticky;  z-index: 1000;  padding: 10px;  border: 1px solid #CCC;  background-color: #FFF;  transition: all 300ms;}
.sticky-top { top: 40px;}
.sticky-bottom { bottom: 40px;}
.is-stuck { background: blue; color: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>some text</p><p>some text</p><p>some text</p><div class="sticky-top"> Sticky to the top!</div>
<p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><p>some text</p><div class="sticky-bottom"> Sticky to the bottom!</div>
<p>some text</p><p>some text</p><p>some text</p><p>some text</p>

position:sticky : Adding style when the element detaches from normal flow

Unfortunately, as far as I know there are no pseudo class that targets the 'sticky' state.

See post: Targeting position:sticky elements that are currently in a 'stuck' state

An alternative would be to use jQuery to add or remove a class/css styling when it reaches the element that needs to be stickied.



Related Topics



Leave a reply



Submit