Skip to content

React + epub.js scrolled-doc: upward scroll snaps back (scroll anchoring issue) — workaround included #1416

Description

@SungWookkk

Hi,

I’m combining my previous symptom report and workaround notes into one issue.

Related: #1303 (comment)

Summary

In scrolled-doc mode (React app), fast upward scrolling causes the viewport to jump back down repeatedly, as if the reader is “pulled” to a previous position.
This is especially visible while sections are loading/injected in continuous scroll mode.

It appears to be caused by browser scroll anchoring interacting with epub.js section rendering.

Environment

  • epub.js (futurepress/epub.js) in React
  • Flow: scrolled-doc
  • Manager: continuous
  • Browser: Chromium-based (also reproducible in other modern browsers)
  • Large EPUB with many sections

Reproduction

  1. Open a large EPUB in scrolled-doc mode.
  2. Scroll down, then scroll up quickly multiple times.
  3. Observe that scroll position intermittently snaps back downward.

Expected

Scrolling should be stable and monotonic (up stays up, down stays down).

Actual

When scrolling up quickly, position jumps back down (rubber-band/snap-back behavior).

Confirmed workaround

Disabling scroll anchoring fixes the issue in my app.

Basic CSS workaround

.epub-container {
  overflow-anchor: none !important;
}

React-side workaround (container + iframe content docs)

useEffect(() => {
  if (!rendition) return;

  // Stage/manager container
  const container = (rendition as any)?.manager?.container as HTMLElement | undefined;
  if (container) container.style.overflowAnchor = "none";

  // Each loaded section document (iframe content)
  (rendition as any).hooks.content.register((contents: any) => {
    const doc = contents?.document as Document | undefined;
    if (!doc) return;

    doc.documentElement.style.setProperty("overflow-anchor", "none", "important");
    doc.body.style.setProperty("overflow-anchor", "none", "important");

    doc.querySelectorAll<HTMLElement>(".epub-container").forEach((el) => {
      el.style.setProperty("overflow-anchor", "none", "important");
    });
  });

  return () => {
    if (container) container.style.removeProperty("overflow-anchor");
  };
}, [rendition]);

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions