30

Let's take take a simple example:

<nav id="#mynav">MY NAVBAR</nav>

and a basic style:

#mynav {
    position : sticky;
}

I would like to apply the following styling information to my navbar only when it detaches from the normal flow, in order to visually split it from the main content (with a shadow in this case)

box-shadow : 0px 10px 15px 0px rgba(0,0,0,0.75);

Is there some kind of pseudo-class or media-query-like thing I could use for that? E.g.:

#mynav:some-pseudo-class {
    box-shadow : 0px 10px 15px 0px rgba(0,0,0,0.75);
}

I know there are good plugins for this, but all of them seem to be unable to implement it whithout bypassing the (quite new) native feature position:sticky. Instead, they do it in an old-fashion way (scroll event, and position:fixed; top:0).

So, is it possible to do it using position:sticky, and without using the scroll event, which slows down the fluidity of the page (I'm not against javascript, but scroll event is too slow)?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
yolenoyer
  • 8,797
  • 2
  • 27
  • 61

3 Answers3

3

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.

Matt Dell
  • 9,205
  • 11
  • 41
  • 58
adamk22
  • 581
  • 4
  • 18
  • @Yako If you check the link I mentioned there are couple of JS code to choose from. – adamk22 Feb 18 '19 at 16:40
  • 1
    Just a quick note on browser support as the top comment is from 2017. Sticky is now well supported by browsers. ie11 is the only browser without support, and represents only 1% of global users at the time of writing. Sticky also degrades gracefully, so your best bet is to go for a css solution if it can fit your needs. See https://caniuse.com/?search=sticky – user2528534 Mar 16 '21 at 11:36
3

I just found the answer here https://css-tricks.com/how-to-detect-when-a-sticky-element-gets-pinned/

As of today you do need to use javascript:

const el = document.querySelector(".myElement")
const observer = new IntersectionObserver( 
  ([e]) => e.target.classList.toggle("is-pinned", e.intersectionRatio < 1),
  { threshold: [1] }
);

observer.observe(el);
#parent { 
  height: 2000px; 
}

.myElement {
  position: sticky;
  top: -1px;
}

/* styles for when the header is in sticky mode */
.myElement.is-pinned {
  color: red;
} 
<div id="parent">
  
  <br />  <br />  <br />  <br />
  <div class="myElement">Hello!</div>
  
</div> 

top: -1px is very important because IntersectionObserver detect "how much your element is visible on the screen". e.intersectionRatio correspond to the percent of "visibility" of your el. So if you use top: 0px then e.intersectionRatio will always equal 1 and the class is-pinned will never be added.

Lenny4
  • 1,215
  • 1
  • 14
  • 33
-1

Your best solution is probably to rely on a JavaScript scroll event. CSS has (limited) support for snap points, but that's the closest it has right now to any sort of scroll event support.

If your only concern with a JS solution is fluidity, I might suggest trying to apply CSS transitions to #mynav so that when the element is altered on scroll, there is a smoother visual cue that something is changing.

Robert
  • 6,881
  • 1
  • 21
  • 26