From eac65c97d8e311b2e463dcb8cdb6e0635d7f9dae Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 5 Aug 2026 16:15:07 -0700 Subject: [PATCH 1/2] fix(docs): stop the sidebar drifting when page content resizes The sidebar used fumadocs' `sticky` positioning, and a sticky box is bottom-limited by its containing block. #nd-docs-layout ends ~660px above the document bottom because the site footer is a sibling of the layout rather than a grid child, so across the whole footer the sidebar was pushed progressively upward. Any content-height change while the reader sat in that zone then moved it: expanding one FAQ row shifted the sidebar 16.8px at a fixed scroll offset, and collapsing it shifted it back. Pin the sidebar and its divider to the viewport instead. A fixed box ignores both the container's end and the document height, so neither the drift nor the jump can happen. The grid columns are explicit (`0px 300px 1fr 268px 0px`), so taking the placeholder out of flow leaves its track intact and the content column does not move. The footer is already opaque and now out-stacks both, so it slides over them at the end of the page. Measured with Playwright before and after: sidebar delta on expand/collapse 16.8px/-16.8px -> 0px/0px, content column left and width unchanged, and the sidebar holds top:92px at the page bottom on the docs, API-reference, academy and integrations layouts. Mobile is untouched (the rule is desktop-only). --- apps/docs/app/global.css | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index 39f705b6510..91c43968efd 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -362,16 +362,33 @@ aside#nd-sidebar [data-radix-scroll-area-viewport] { min-height: var(--fd-docs-height) !important; } - /* Sidebar divider line — sticky within the docs layout box, so it ends where - the layout does instead of bleeding into (or past) the footer below it. - #nd-docs-layout is a CSS grid (see fumadocs' Container slot); a sticky - pseudo-element stays in normal flow, so without an explicit grid-area it - gets auto-placed into a real content cell and skews that cell's sizing. - Spanning the full grid keeps it purely decorative/overlaid instead. */ + /* Pin the sidebar to the viewport instead of letting fumadocs' `sticky` do it. + A sticky box is bottom-limited by its containing block, and #nd-docs-layout + ends ~660px above the document bottom because the site footer is a sibling + of the layout, not a grid child. So across the whole footer the sidebar gets + pushed upward — and any content-height change while the reader is in that + zone (expanding an FAQ row, say) makes it visibly jump. A fixed box ignores + both the container's end and the document's height, so neither happens. + + Safe because the grid columns are explicit (`0px 300px 1fr 268px 0px`), so + removing the placeholder from flow leaves its track intact. `left`/`width` + are restated because a fixed box no longer derives them from its grid cell, + and `top`/`height` already come from fumadocs' own utility classes. */ + [data-sidebar-placeholder] { + position: fixed !important; + left: var(--sidebar-offset); + width: var(--fd-sidebar-width); + } + + /* Sidebar divider line — pinned for the same reason, and to stay glued to the + sidebar's right edge. #nd-docs-layout is a CSS grid (see fumadocs' Container + slot); the pseudo-element spans the full grid so it reads as decorative + overlay rather than being auto-placed into a real content cell and skewing + that cell's sizing. */ #nd-docs-layout::before { content: ""; display: block; - position: sticky; + position: fixed; grid-row: 1 / -1; grid-column: 1 / -1; top: 92px; /* below navbar */ @@ -383,6 +400,14 @@ aside#nd-sidebar [data-radix-scroll-area-viewport] { z-index: 21; } + /* The footer is opaque and now has to out-stack the pinned sidebar and its + divider (z-index 20 and 21), so it slides over them at the end of the page + rather than being drawn through. */ + footer { + position: relative; + z-index: 22; + } + /* Hide fumadocs nav on desktop - we use custom navbar there */ #nd-docs-layout > header { display: none !important; From 94d92355e4c612ad1206177cb739c136ea229e4c Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 5 Aug 2026 16:22:19 -0700 Subject: [PATCH 2/2] refactor(docs): drop dead grid placement, move footer stacking to the component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review follow-ups. The divider's `grid-row`/`grid-column` stopped doing anything the moment it became `position: fixed` — a fixed box is out of grid layout entirely — so they and the comment explaining the grid span were describing positioning that no longer happens. Verified inert: the divider still computes to left 300px / width 1px / z-index 21 without them. The footer's stacking context also belongs on the footer, not in a global rule matching every desktop `footer` element, so it moves to the component as `relative z-[22]` with the reason in its TSDoc. --- apps/docs/app/global.css | 19 ++++--------------- apps/docs/components/footer/footer.tsx | 9 ++++++++- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/apps/docs/app/global.css b/apps/docs/app/global.css index 91c43968efd..5f6ea80f42d 100644 --- a/apps/docs/app/global.css +++ b/apps/docs/app/global.css @@ -380,17 +380,14 @@ aside#nd-sidebar [data-radix-scroll-area-viewport] { width: var(--fd-sidebar-width); } - /* Sidebar divider line — pinned for the same reason, and to stay glued to the - sidebar's right edge. #nd-docs-layout is a CSS grid (see fumadocs' Container - slot); the pseudo-element spans the full grid so it reads as decorative - overlay rather than being auto-placed into a real content cell and skewing - that cell's sizing. */ + /* Sidebar divider line — pinned for the same reason, and so it stays glued to + the sidebar's right edge. Being fixed takes it out of #nd-docs-layout's grid + entirely, so it needs no grid placement and cannot skew a content cell; its + position comes from `left`/`top` alone. */ #nd-docs-layout::before { content: ""; display: block; position: fixed; - grid-row: 1 / -1; - grid-column: 1 / -1; top: 92px; /* below navbar */ height: calc(100dvh - 92px); left: calc(var(--sidebar-offset) + var(--fd-sidebar-width)); @@ -400,14 +397,6 @@ aside#nd-sidebar [data-radix-scroll-area-viewport] { z-index: 21; } - /* The footer is opaque and now has to out-stack the pinned sidebar and its - divider (z-index 20 and 21), so it slides over them at the end of the page - rather than being drawn through. */ - footer { - position: relative; - z-index: 22; - } - /* Hide fumadocs nav on desktop - we use custom navbar there */ #nd-docs-layout > header { display: none !important; diff --git a/apps/docs/components/footer/footer.tsx b/apps/docs/components/footer/footer.tsx index 698aa012475..75896de0aed 100644 --- a/apps/docs/components/footer/footer.tsx +++ b/apps/docs/components/footer/footer.tsx @@ -130,9 +130,16 @@ function FooterColumn({ title, items }: { title: string; items: FooterItem[] }) ) } +/** + * Site footer. + * + * `relative z-[22]` stacks it above the docs sidebar (z-20) and that sidebar's + * divider (z-21), both of which are pinned to the viewport, so the footer slides + * over them at the end of the page instead of being drawn through. + */ export function Footer() { return ( -