Skip to content

Commit 04766ed

Browse files
MENDELU: reserve the scrollbar gutter so the page stops shifting on reload (#1406)
On reload the home page content jumps ~7.5px to the right and back. While Angular boots it replaces the server-rendered DOM, so for a moment the page is too short to scroll: the vertical scrollbar disappears and then returns, the viewport widens 1425 -> 1440 -> 1425, and every centred container slides half a scrollbar width sideways. The anti-flicker overlay cannot hide this one -- the overlay lives inside the page, so it shifts along with everything else. Reserve the scrollbar's width permanently (scrollbar-gutter: stable, with an overflow-y: scroll fallback for older engines) so its appearance/disappearance is a no-op for layout. ng-bootstrap pads the body by the scrollbar width when a modal opens; with the gutter always reserved that compensation becomes surplus and would itself shift the page ~7.5px, so it is cancelled for body.modal-open. Measured on the dev instance (dev-6.pc:8573), logged out, headed browser, short viewport, overlay active: reload content shift 7.5px -> 0px modal open shift -7.5px -> 0px (after the modal-open cancel) This is the same fix already applied to the UoE/datashare frontend. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 29b88bf commit 04766ed

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

src/styles/_global-styles.scss

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,35 @@
11
html {
22
position: relative;
33
min-height: 100%;
4+
5+
// Always reserve the vertical scrollbar's width. While Angular boots it replaces the
6+
// server-rendered DOM, so the page is briefly too short to scroll: the scrollbar disappears and
7+
// then comes back, widening and re-narrowing the viewport and sliding every centred container
8+
// sideways by half the scrollbar width (~7.5px right, then back). The anti-flicker overlay cannot
9+
// hide that, because the overlay lives in the page and shifts with it.
10+
scrollbar-gutter: stable;
11+
}
12+
13+
// scrollbar-gutter is unsupported before Chrome 94 / Firefox 97 / Safari 16; keeping the scrollbar
14+
// track permanently visible reserves the same width there.
15+
@supports not (scrollbar-gutter: stable) {
16+
html {
17+
overflow-y: scroll;
18+
}
419
}
520

621
body {
722
overflow-x: hidden;
823
}
924

25+
// ng-bootstrap pads the body by the scrollbar width when a modal opens, to compensate for the
26+
// scrollbar it is about to hide. With the gutter reserved above, that width is never actually freed,
27+
// so the compensation is pure surplus and shifts the page left by half of it -- the very thing the
28+
// reserved gutter exists to prevent. Cancel it; the gutter already keeps the width steady.
29+
body.modal-open {
30+
padding-right: 0 !important;
31+
}
32+
1033
// Sticky Footer
1134
.outer-wrapper {
1235
display: flex;

0 commit comments

Comments
 (0)