ui: reserve the scrollbar gutter so the top bar stops shifting between pages

Pages tall enough to scroll showed a ~15px scrollbar; short pages didn't — so the
centered top bar jumped left/right as you navigated. scrollbar-gutter: stable on html
(SPA app.css + the server-rendered share pages) keeps the layout width constant. No-op
on overlay-scrollbar platforms (mobile), which never shifted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jay
2026-06-30 04:52:59 -04:00
parent 3740e09d02
commit 86d9897113
3 changed files with 6 additions and 1 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

+4 -1
View File
@@ -34,7 +34,10 @@
} }
* { box-sizing: border-box; } * { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; } /* Always reserve the scrollbar gutter so the centered top bar / content doesn't jump
left-right between pages that scroll and pages that don't. (No-op on overlay-scrollbar
platforms like mobile, which never shifted anyway.) */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scrollbar-gutter: stable; }
body { body {
margin: 0; margin: 0;
background: var(--bg); background: var(--bg);
+2
View File
@@ -60,6 +60,8 @@ def _back_link_html(label: str = "Back") -> str:
# Ported verbatim from HubBar.svelte's <style> (+ HubShell's .back), scoped to the same # Ported verbatim from HubBar.svelte's <style> (+ HubShell's .back), scoped to the same
# class names so the bar looks pixel-identical to the SPA regardless of page palette. # class names so the bar looks pixel-identical to the SPA regardless of page palette.
_TOP_BAR_CSS = """ _TOP_BAR_CSS = """
/* reserve the scrollbar gutter so the bar doesn't jump left-right between pages */
html { scrollbar-gutter: stable; }
@font-face { font-family:'Hanken Grotesk'; src:url('/fonts/hanken-var.woff2') format('woff2'); font-weight:400 700; font-style:normal; font-display:swap; } @font-face { font-family:'Hanken Grotesk'; src:url('/fonts/hanken-var.woff2') format('woff2'); font-weight:400 700; font-style:normal; font-display:swap; }
header.bar { display:flex; align-items:center; justify-content:space-between; max-width:1180px; width:100%; margin:0 auto; box-sizing:border-box; padding:26px clamp(18px,5vw,44px) 0; font-family:'Hanken Grotesk',ui-sans-serif,system-ui,sans-serif; background:none; border:none; } header.bar { display:flex; align-items:center; justify-content:space-between; max-width:1180px; width:100%; margin:0 auto; box-sizing:border-box; padding:26px clamp(18px,5vw,44px) 0; font-family:'Hanken Grotesk',ui-sans-serif,system-ui,sans-serif; background:none; border:none; }
header.bar .brand { display:block; line-height:0; } header.bar .brand { display:block; line-height:0; }