catalin.red

“Activatable” Shadow on Sticky Elements


Imagine if you had two vertically overlapping elements, where the top element sticks and the only the bottom element scrolls.

JSFiddle

With CSS3, the only code we need to achieve the above effect is 2 lines of CSS:

position: sticky;
top: 0;

All that the sticky positioning does it switch between relative and fixed positioning to achieve the effect of an element “sticking” to the offset you specify with top , bottom , left , and right .

thecontextofthings.com

But there is one glaring issue with this feature in certain situations. It’s especially apparent when the two overlapping elements’ background colors are the same:

  • Once they start scrolling, the lack of a visible separator makes it hard to tell where the overlapping content meets the overlapped content.

Sure enough, it looks a lot better with a simple drop shadow:

box-shadow: 0px 0.5px 0.5px 1.5px rgba(0,0,0,0.75);

Looks pretty good, right?

tenor.com

The shadow looks good when content has actually overlapped, but it looks awkward in the initial resting state, when nothing is actually overlapping.

Ideally, we wouldn’t show a shadow in the initial state, and only show it when the user has started scrolling. Unfortunately, there is no event or pseudo element that triggers when the sticky element changes between relative and fixed positions.

The search results are pretty disheartening and the most helpful post is from a developer saying that you should use the IntersectionObserver API.

The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document’s viewport.

. . . 🙃

But your UX is counting on you to get this feature in the MVP.
What do you do?

reddit.com

No wait! There’s a way to do it with CSS.

All you need to do is create an element to initially “cover” the shadow, and when the user scrolls down, it starts uncovering the shadow.

When the user scrolls down, the shadow element doesn’t move because it “sticks” to its current position and the cover moves up, gradually “uncovering” the shadow element.

JSFiddle

tenor.com

Enjoy yet another beautiful hack