Skip to content

Fix scroll progress bar showing 100% with no overflow#3652

Open
mattgperry wants to merge 1 commit intomainfrom
worktree-fix-issue-2950
Open

Fix scroll progress bar showing 100% with no overflow#3652
mattgperry wants to merge 1 commit intomainfrom
worktree-fix-issue-2950

Conversation

@mattgperry
Copy link
Collaborator

Summary

  • Fixes scroll progress immediately reporting 100% when a scroll container has no overflow (scrollHeight === clientHeight)
  • The progress() utility returns 1 for a zero-width range (progress(0, 0, 0) === 1), which is correct for animations (zero-duration = complete) but wrong for scroll (no overflow = nothing scrolled)
  • Added a guard in updateAxisInfo to return 0 progress when scrollLength is 0

Fixes #2950

Test plan

  • Added unit test: "Reports zero progress when container has no scroll overflow"
  • Verified test fails without the fix (progress returns 1 → 100%)
  • Verified test passes with the fix
  • All existing scroll tests pass (17/17)
  • Full yarn test passes
  • yarn build succeeds

🤖 Generated with Claude Code

When a scroll container has no overflow (scrollHeight === clientHeight),
scrollLength is 0. The progress() utility returns 1 for a zero range,
causing scroll progress to immediately report 100% instead of 0%.

This guards against the zero scrollLength case in updateAxisInfo,
returning 0 progress when there is nothing to scroll.

Fixes #2950

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@greptile-apps
Copy link

greptile-apps bot commented Mar 17, 2026

Greptile Summary

This PR fixes a bug where a scroll progress bar would immediately report 100% progress when a scroll container has no overflow (scrollHeight === clientHeight). The root cause was that the shared progress() utility intentionally returns 1 for a zero-width range (semantically: "complete instantly"), which is correct for animations but wrong for scroll tracking where no scrollable area means nothing has been scrolled.

Key changes:

  • info.ts: A one-line guard in updateAxisInfo short-circuits to 0 when scrollLength === 0, bypassing the progress(0, 0, 0) === 1 behavior.
  • index.test.ts: A new unit test sets clientHeight === scrollHeight (zero overflow) and asserts that scrollLength and progress are both 0.

Minor observation:

  • The new test only asserts the y-axis values — the x-axis code path (same guard, same function) is not covered by the new assertion, though the fix applies to both axes symmetrically.

Confidence Score: 5/5

  • This PR is safe to merge — the fix is minimal, correct, and well-tested.
  • The change is a single-line guard with no side effects on the existing scroll tracking logic. The progress utility's behavior for zero-ranges is well-understood, and the guard correctly special-cases the scroll context. The new test validates the fix, all existing 17 scroll tests continue to pass, and the build succeeds.
  • No files require special attention.

Important Files Changed

Filename Overview
packages/framer-motion/src/render/dom/scroll/info.ts Single-line guard added to updateAxisInfo to return 0 progress when scrollLength is 0, correctly preventing the progress utility's zero-range behavior (progress(0,0,0) === 1) from propagating to scroll consumers.
packages/framer-motion/src/render/dom/scroll/tests/index.test.ts New test verifies zero progress when container has no scroll overflow. Only the y-axis is asserted; the x-axis fix in updateAxisInfo is untested. Test follows the established new Promise&lt;void&gt;(async (resolve) =&gt; {...}) pattern already used 14+ times in this file.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[updateAxisInfo called] --> B["Compute scrollLength\n(scrollHeight - clientHeight)"]
    B --> C{scrollLength === 0?}
    C -- "Yes (no overflow)" --> D["axis.progress = 0\n✅ Bug fixed"]
    C -- "No (has overflow)" --> E["axis.progress = progress(0, scrollLength, current)\n✅ Normal path"]
    E --> F["progress utility\nreturns value / scrollLength"]
    D --> G[Scroll info emitted to consumer]
    F --> G

    style D fill:#d4edda,stroke:#28a745
    style C fill:#fff3cd,stroke:#ffc107
Loading

Last reviewed commit: c404206

Comment on lines +439 to +440
expect(latest.y.scrollLength).toEqual(0)
expect(latest.y.progress).toEqual(0)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 X-axis progress not asserted

The fix in updateAxisInfo applies to both the x and y axes, but the test only asserts latest.y. Consider also asserting latest.x.scrollLength and latest.x.progress to give symmetric coverage of the guard:

Suggested change
expect(latest.y.scrollLength).toEqual(0)
expect(latest.y.progress).toEqual(0)
expect(latest.y.scrollLength).toEqual(0)
expect(latest.y.progress).toEqual(0)
expect(latest.x.scrollLength).toEqual(0)
expect(latest.x.progress).toEqual(0)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Scroll progress bar doesn't work properly

1 participant