Skip to content

[BUGFIX] Fix sticky header scroll flicker in Chromium browsers#1618

Open
CybotTM wants to merge 8 commits into
benjaminkott:masterfrom
netresearch:bugfix/sticky-header-scroll-flicker
Open

[BUGFIX] Fix sticky header scroll flicker in Chromium browsers#1618
CybotTM wants to merge 8 commits into
benjaminkott:masterfrom
netresearch:bugfix/sticky-header-scroll-flicker

Conversation

@CybotTM
Copy link
Copy Markdown

@CybotTM CybotTM commented Mar 14, 2026

Problem

The sticky navigation bar flickers when scrolling through the transition zone in Chromium-based browsers (Chrome, Edge). This has been reported in #1424 and #1468, affects the official demo site, and has been open since January 2024.

Root cause

bootstrap.stickyheader.js uses a hardcoded 120px scroll threshold:

120 < window.scrollY
    ? stickyheader[0].classList.add("navbar-transition")
    : stickyheader[0].classList.remove("navbar-transition");

Since .navbar-fixed-top uses position: sticky, the navbar stays in document flow. When navbar-transition is added, --mainnavigation-nav-height changes from the responsive default (100-110px on desktop) to 70px. This height reduction shifts document content upward, which changes scrollY, which can drop it back below 120px, removing the class, restoring the height, shifting content back down — creating a feedback loop.

Fix

Two changes:

  1. Replace hardcoded 120px with getBoundingClientRect().bottom — dynamically adapts to the actual navbar height at any breakpoint, so the threshold matches the element's real position.

  2. Check classList.contains() before toggling — prevents redundant DOM mutations when the class is already in the desired state.

if (window.scrollY >= stickyheader[0].getBoundingClientRect().bottom &&
    !stickyheader[0].classList.contains("navbar-transition")) {
    stickyheader[0].classList.add("navbar-transition");
} else if (window.scrollY < stickyheader[0].getBoundingClientRect().bottom &&
    stickyheader[0].classList.contains("navbar-transition")) {
    stickyheader[0].classList.remove("navbar-transition");
}

Why this works

  • getBoundingClientRect().bottom returns the navbar's current bottom edge relative to the viewport. With position: sticky; top: 0, this equals the navbar's current height.
  • When the navbar is in its expanded state (no navbar-transition), bottom equals the full height (e.g., 110px). The class is only added once scrollY exceeds this value.
  • When navbar-transition is active and the navbar has shrunk, bottom equals the reduced height (70px). The class is only removed when scrollY drops below this smaller value.
  • This creates natural hysteresis: the "add" threshold (110px) is higher than the "remove" threshold (70px), eliminating the oscillation zone.

Note: An alternative CSS-only approach exists (see #1619) that fixes the root cause (document height instability) rather than the symptom. Both approaches are valid and can be combined.

Credit: Solution based on community contributions in #1468 by @howie-f, @danscheer, and @SventB.

Resolves #1424
Resolves #1468

Prerequisites

  • CSS has been rebuilt (no SCSS changes in this PR)
  • Minified JS has been rebuilt

CybotTM added 5 commits March 14, 2026 19:46
The hardcoded 120px scroll threshold causes a feedback loop in
Chromium browsers: at the threshold, adding navbar-transition
changes the navbar height (position:sticky), which shifts document
content, which changes scrollY, which toggles the class back,
creating constant flickering.

Replace the hardcoded threshold with getBoundingClientRect().bottom
which dynamically adapts to the actual navbar height. Additionally,
check classList.contains() before toggling to prevent redundant
DOM mutations.

Resolves: benjaminkott#1424
Resolves: benjaminkott#1468
The JS workaround is no longer needed. The root cause (document height
instability) is fixed in _transition.scss by compensating with
margin-bottom.
The navbar uses position:sticky, so height changes affect document
flow. When navbar-transition reduces --mainnavigation-nav-height to
the xs value (70px), the document shrinks, causing scrollbar jumps
and scroll-position oscillation in Chromium browsers.

Add compensating margin-bottom computed from $navbar-heights map:
the difference between each breakpoint's default height and the
transition height (xs). This keeps document height constant while
the navbar still visually shrinks.

Resolves: benjaminkott#1424
Resolves: benjaminkott#1468
@CybotTM CybotTM changed the title [BUGFIX] Fix sticky header scroll flicker in Chromium browsers [BUGFIX] Fix sticky header scroll flicker via CSS height compensation Mar 14, 2026
CybotTM added 3 commits March 14, 2026 20:15
Restores the JS fix that was incorrectly reverted. This PR addresses
the scroll flicker symptom via dynamic threshold.
@CybotTM CybotTM changed the title [BUGFIX] Fix sticky header scroll flicker via CSS height compensation [BUGFIX] Fix sticky header scroll flicker in Chromium browsers Mar 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flickering Sticky Navigation Home page header flashes when scrolled to a certain position

1 participant