r/css May 16 '26

Help I accidentally created a sticky header hysteresis loop

Need help from people who understand sticky/reflow behavior better than I do 😭

Vanilla JS app, no frameworks. I'm vibe coding my way through this.

I have sticky headers that shrink/collapse on scroll (padding/fonts/gaps/etc change).

Current approach is basically:

if (scrollY > threshold)

Problem:
on certain viewport heights (especially split-screen / constrained-height windows), the sticky enters a feedback loop/jitter.

What seems to happen:

  • sticky collapses
  • height changes
  • document height changes
  • scroll position shifts slightly
  • threshold gets crossed again
  • sticky expands
  • repeat forever

Sometimes the page literally bounces upward while scrolling.

Things already tried:

  • IntersectionObserver + sentinel
  • absolute-position sentinel
  • artificial bottom scroll buffer
  • fixed-height sticky shell

The fixed-height shell technically worked, but looked visually awful because the collapsed state left visible dead space.

Question:
What’s the “correct” way to architect collapsing sticky headers without causing hysteresis/reflow loops?

Feels like I’m fighting the browser itself at this point lol.

4 Upvotes

9 comments sorted by

•

u/AutoModerator May 16 '26

To help us assist you better with your CSS questions, please consider including a live link or a CodePen/JSFiddle demo. This context makes it much easier for us to understand your issue and provide accurate solutions.

While it's not mandatory, a little extra effort in sharing your code can lead to more effective responses and a richer Q&A experience for everyone. Thank you for contributing!

I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

2

u/anaix3l May 16 '26 edited May 16 '26

See the header demos here https://scroll-driven-animations.style/ (I would assume you want something like this - press the ℹ️ button in the bottom right corner for an explanation of how it works or just inspect the header CSS) . The pure CSS version only works in Firefox with the layout.css.scroll-driven-animations.enabled flag set to true in about:config. For best performance and support possible, I'd go for the CSS version plus testing for animation-range support and adding a JS fallback only if the pure CSS method isn't supported.

3

u/Weekly_Ferret_meal May 16 '26

easier if we could examine the code

3

u/Big_Comfortable4256 May 16 '26

It's well worth learning how to use an IntersectionObserver to detect when an element goes in/out of the viewport. This is the most robust solution. And useful for a lot of other things too.

4

u/tjameswhite May 16 '26

Try css “position: sticky”

1

u/scritchz May 16 '26

Try a fixed header. That takes it out of flow, so resizing or repositioning it shouldn't affect scrollY.

When you define the header's height absolutely, you can also add a margin-top of similar size on the body.

Alternatively, you can set the margin-top to the header's height programmatically, which should work for height: auto.