From 63e1bbbeebb31baccce99e973c819bbbf6ab0f24 Mon Sep 17 00:00:00 2001 From: Contributolo Date: Mon, 16 Mar 2026 19:12:15 +1100 Subject: [PATCH 1/2] Fix: Sticky header with shrink overlaps content at scrollY=0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix: Sticky header with shrink overlaps content when scrolling back to top Problem When using an Advanced Header with Sticky + Shrink Main Row enabled (data-sticky="1", data-shrink-main="1"), scrolling down and then back to scrollY=0 causes the header to overlap approximately 80–90px of page content. Reproduction Create an Advanced Header with Sticky Header and Shrink Main Row (e.g. shrink height 80px) Load any page using this header Scroll down past the header trigger point (header shrinks and becomes fixed — works correctly) Scroll back to the top (scrollY=0) Bug: Header overlaps page content Root Cause Two timing issues in updateSticky(): 1. Placeholder height uses stale measurement — elHeight is read at line ~486 while the header row is still shrunk. The placeholder gets this stale value at line ~494. The shrink block then correctly restores the row height at line ~571, but the placeholder was already set too small. 2. isSticking is one frame behind — The position block at line ~597 uses the previous frame's isSticking value (still true). setStickyChanged(false) runs afterwards at line ~654, but since no further scroll event fires at scrollY=0, position: fixed persists. Combined: the header stays position: fixed at ~178px, but its placeholder is only ~88px — the 90px gap causes content overlap. Measured values Phase scrollY placeholder wrapper position ───────────── ─────── ─────────── ─────── ──────── Fresh load 0 170px 170px static ✓ Scrolled down 600 80px 88px fixed ✓ Back at top 0 88px 178px fixed ✗ BUG After fix 0 170px 170px static ✓ Fix Adds a correction block at the end of updateSticky() that runs after both the shrink logic and the class/position logic have completed. At scrollY === 0 with shrink enabled, it resets position to initial and re-measures the placeholder height from the now-restored wrapper. This is a minimal, non-breaking change — it only activates at the exact scroll position where the bug manifests and does not alter the existing control flow. --- src/assets/js/kb-header-block.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/assets/js/kb-header-block.js b/src/assets/js/kb-header-block.js index f770f07a6..ec108e34c 100644 --- a/src/assets/js/kb-header-block.js +++ b/src/assets/js/kb-header-block.js @@ -712,6 +712,27 @@ class KBHeader { parent.classList.remove('child-is-fixed'); document.body.classList.remove('header-is-fixed'); } + // Fix stale placeholder height and position when back at top. + // + // Two timing issues cause the header to overlap page content at scrollY=0: + // 1. elHeight (line ~486) is measured before the shrink block (line ~571) + // restores the header row, so placeholderWrapper gets the shrunk value. + // 2. isSticking (used at line ~597) reflects the previous scroll frame, + // so position:fixed persists even though setStickyChanged(false) runs + // afterwards. + // + // Re-measuring and resetting here — after both shrink and class logic + // have completed — corrects both issues in a single pass. + if ( window.scrollY === 0 && this.shrinkMain ) { + this.stickyWrapper.style.position = 'initial'; + this.stickyWrapper.style.width = 'initial'; + this.stickyWrapper.style.left = 'initial'; + this.stickyWrapper.style.top = 'initial'; + + if ( ! isTransparent || hasStickySection ) { + this.placeholderWrapper.style.height = this.stickyWrapper.offsetHeight + 'px'; + } + } } activeSizeCased(size) { From 0866a419c1ebbc81434203c7bffe980995488e6b Mon Sep 17 00:00:00 2001 From: Contributolo Date: Wed, 25 Mar 2026 09:38:18 +1100 Subject: [PATCH 2/2] Refactor sticky header position logic The initial fix reset position and re-measured placeholder height at scrollY=0 for all shrink-enabled headers. This caused a regression on pages using transparent + sticky + shrink headers (e.g. homepage with data-transparent="1"): the sticky background color persisted when scrolling back to the top instead of reverting to the transparent state. The fix now uses the same guard condition Kadence already applies for placeholder height on line ~493: ! isTransparent || hasStickySection. Transparent headers without a sticky section are skipped entirely, since they overlay content by design and don't use a sized placeholder. --- src/assets/js/kb-header-block.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/assets/js/kb-header-block.js b/src/assets/js/kb-header-block.js index ec108e34c..03cc40c83 100644 --- a/src/assets/js/kb-header-block.js +++ b/src/assets/js/kb-header-block.js @@ -723,15 +723,12 @@ class KBHeader { // // Re-measuring and resetting here — after both shrink and class logic // have completed — corrects both issues in a single pass. - if ( window.scrollY === 0 && this.shrinkMain ) { - this.stickyWrapper.style.position = 'initial'; + if ( window.scrollY === 0 && this.shrinkMain && ( ! isTransparent || hasStickySection ) ) { this.stickyWrapper.style.position = 'initial'; this.stickyWrapper.style.width = 'initial'; this.stickyWrapper.style.left = 'initial'; this.stickyWrapper.style.top = 'initial'; - - if ( ! isTransparent || hasStickySection ) { - this.placeholderWrapper.style.height = this.stickyWrapper.offsetHeight + 'px'; - } + + this.placeholderWrapper.style.height = this.stickyWrapper.offsetHeight + 'px'; } }