fix(reader): reset scroll to top on paginated fit-width page turn (#4683) (#4695)

In paginated fixed-layout mode (PDF / fixed-layout EPUB) with fit-width zoom, a
page taller than the viewport makes the renderer host scroll vertically. Turning
the page kept the previous page's vertical offset, so the next page opened
scrolled to the end instead of the top. The bug only shows on WebKit
(Linux/iOS/macOS), which preserves the scroll offset across the page content
swap; Blink (Android/Chrome) resets it to zero.

Bump foliate-js to the fix (readest/foliate-js#34): reset scrollTop on a page
turn only. Add a unit test for the new computePaginatedScroll helper.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Huang Xin
2026-06-21 13:46:33 +08:00
committed by GitHub
parent 9e163fe746
commit 2153f7cc0c
2 changed files with 41 additions and 1 deletions
@@ -0,0 +1,40 @@
import { describe, expect, it } from 'vitest';
import { computePaginatedScroll } from 'foliate-js/fixed-layout.js';
describe('fixed-layout paginated page-turn scroll reset', () => {
it('resets the vertical scroll to the top of the page on a page turn (#4683)', () => {
// A tall fit-width page leaves the host scrolled to the bottom; turning to
// the next page must start at the top, not inherit the previous offset.
expect(
computePaginatedScroll({
elementWidth: 800,
containerWidth: 800,
scrollTop: 1200,
pageTurn: true,
}),
).toEqual({ scrollLeft: 0, scrollTop: 0 });
});
it('preserves the vertical scroll on a non-navigation re-render (resize/zoom/theme)', () => {
expect(
computePaginatedScroll({
elementWidth: 800,
containerWidth: 800,
scrollTop: 1200,
pageTurn: false,
}),
).toEqual({ scrollLeft: 0, scrollTop: 1200 });
});
it('re-centers horizontally when the page is wider than the viewport', () => {
expect(
computePaginatedScroll({
elementWidth: 1200,
containerWidth: 800,
scrollTop: 0,
pageTurn: true,
}),
).toEqual({ scrollLeft: 200, scrollTop: 0 });
});
});