fix(driver): scroll off-screen elements into view in fast visibility algorithm#33736
Draft
mschile wants to merge 11 commits into
Draft
fix(driver): scroll off-screen elements into view in fast visibility algorithm#33736mschile wants to merge 11 commits into
mschile wants to merge 11 commits into
Conversation
…ity check (#33045) When experimentalFastVisibility is enabled, the fast algorithm uses elementFromPoint() which only detects elements within the viewport. Elements below the fold were incorrectly reported as hidden. Before point-sampling, check if the element is outside the viewport and scroll it into view using scrollIntoView() with the scrollBehavior config setting. This matches the scroll behavior of action commands like cy.click(). When scrollBehavior is false, off-screen elements remain hidden (no scroll).
Extract the scrollBehavior → ScrollLogicalPosition map into util/scrollBehavior.ts so actionability.ts and fastIsHidden.ts share one source of truth instead of maintaining duplicate copies. Also adds the missing changelog entry under the 15.15.0 Bugfixes section.
…cestor scrollIntoView walks up to the nearest scrollable ancestor — including elements with overflow: hidden, which are programmatically scrollable even though they're not user-scrollable. Scrolling such an ancestor exposed content the test author intentionally clipped, breaking tests that asserted clipped elements should NOT be visible (e.g. the overflow-and-transform slider in driver/e2e/visibility, and the overflow-flex-container fixture where out-of-bounds flex items are checked alongside in-bounds ones). Walk up the DOM before scrolling: if any ancestor has overflow-x or overflow-y of hidden or clip, skip the scroll. Point-sampling on the unscrolled rect correctly reports the element as hidden because elementFromPoint returns null for coordinates outside the viewport.
mschile
added a commit
to cypress-io/cypress-documentation
that referenced
this pull request
May 4, 2026
Elements inside overflow: hidden / clip ancestors are not scrolled into view, since scrollIntoView would programmatically scroll the clipping container and expose content the test author intentionally clipped. Pairs with cypress-io/cypress#33736.
cypress
|
||||||||||||||||||||||||||||
| Project |
cypress
|
| Branch Review |
mschile/pensive-rubin-df92b9
|
| Run status |
|
| Run duration | 19m 12s |
| Commit |
|
| Committer | Matthew Schile |
| View all properties for this run ↗︎ | |
| Test results | |
|---|---|
|
|
0
|
|
|
11
|
|
|
1092
|
|
|
0
|
|
|
24798
|
| View all changes introduced in this branch ↗︎ | |
Warning
No Report: Something went wrong and we could not generate a report for the Application Quality products.
The clipping-ancestor guard was returning true if any ancestor had
overflow-x OR overflow-y of hidden/clip — which incorrectly blocked vertical
scrolling for elements below the fold under the common
body { overflow-x: hidden } pattern. Per CSS spec, setting one axis to a
non-visible value leaves the other axis scrollable.
Pass the bounding rect to determine which axis is off-screen, and only
consider an ancestor clipping if it clips on that same axis. Adds a
regression test covering the body { overflow-x: hidden } case.
2 tasks
…bin-df92b9 # Conflicts: # cli/CHANGELOG.md
…bin-df92b9 # Conflicts: # cli/CHANGELOG.md
cacieprins
approved these changes
May 6, 2026
…bin-df92b9 # Conflicts: # cli/CHANGELOG.md
…bin-df92b9 # Conflicts: # cli/CHANGELOG.md
…bin-df92b9 # Conflicts: # cli/CHANGELOG.md
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 10574c4. Configure here.
…s bounds Many UI patterns use overflow: hidden for cosmetic clipping (border-radius rounding, layout containment) without intent to hide their child content. The previous check returned true any time an off-screen subject had an overflow: hidden ancestor on the same axis, which produced false negatives: in-bounds children of `overflow: hidden` cards below the fold were reported hidden even though scrolling would correctly bring them into view. Now we also call getBoundingClientRect on each candidate ancestor and only short-circuit when the subject is actually outside the ancestor's bounds on the off-screen axis. Adds a regression test for an in-bounds child of an overflow: hidden card below the fold.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

scrollBehaviordirected visibility preprocessing #33045Additional details
When
experimentalFastVisibilityis enabled, the fast visibility algorithm usesdocument.elementFromPoint()for point-sampling. That API only detects elements within the browser viewport, so elements scrolled below the fold were incorrectly reported as hidden — even though they were just out of view, not actually hidden by CSS.The fix preprocesses subjects in
fastIsHidden: if the element's bounding rect lies outside the viewport, scroll it into view per thescrollBehaviorconfig (usingbehavior: 'instant'for synchronous scrolling) and then re-sample. This matches the scroll behavior of action commands likecy.click(), which already scroll before their visibility checks.Subjects with a clipping ancestor are excluded from the scroll preprocessing.
scrollIntoViewwalks up to the nearest scrollable ancestor — including elements withoverflow: hidden, which are programmatically scrollable even though they're not user-scrollable. Scrolling such an ancestor would expose content the test author intentionally clipped (e.g. inputs in a transform-based slider, or out-of-bounds flex items in anoverflow: hiddenflex container). When any ancestor hasoverflow-x/overflow-yofhiddenorclip, we skip the scroll and let point-sampling identify the element as hidden via the unscrolled rect.When
scrollBehavioris set tofalse, off-screen elements remain hidden — no scroll is performed.Elements positioned outside the scrollable document bounds (e.g.
position: absolute; top: -100px) still report as hidden, sincescrollIntoViewcannot bring them into view.Note
Medium Risk
Changes core
experimentalFastVisibilitybehavior by scrolling elements during visibility checks, which could affect test outcomes/performance in edge cases involving overflow clipping and scroll configuration. Scope is limited to the experimental fast algorithm and is covered by new/updated driver e2e tests.Overview
Fixes
experimentalFastVisibilityso elements that are merely below the fold are no longer reported as hidden:fastIsHiddennow scrolls off-screen subjects into view (respectingscrollBehavior, and skipping whenscrollBehavior: false).Adds guards to avoid scrolling when an ancestor would clip the element on the off-screen axis (to preserve intentional
overflow: hidden/clipbehavior), plus sharedscrollBehavior→scrollIntoViewmapping via newscrollBehaviorOptionsMaputil.Expands the driver visibility e2e suite and fixtures with new scrollable viewport scenarios and explicit tests for scrolling behavior,
scrollBehavior: false, and clipping-ancestor edge cases, and documents the updated behavior in the fast-visibility migration guide and CLI changelog.Reviewed by Cursor Bugbot for commit f9a076b. Bugbot is set up for automated code reviews on this repo. Configure here.
Steps to test
experimentalFastVisibility: trueincypress.config.cy.get('.below-fold-element').should('be.visible')— passes on this branch, fails ondevelop.scrollBehavior: falseand re-run — assertion fails (expected, since we no longer scroll).yarn workspace @packages/driver cypress:run -- --spec cypress/e2e/dom/visibility.cy.ts. The newscrollable-viewport-scenariossection and the two explicit off-screen tests cover both the success path and thescrollBehavior: falsecase acrosslegacyandfastmodes.cypress/e2e/e2e/visibility.cy.jsto verify thewith overflow and transform - sliderandoverflow-flex-containercases — these exercise the clipping-ancestor exclusion (subjects clipped byoverflow: hiddenare not scrolled into view).How has the user experience changed?
Users with
experimentalFastVisibilityenabled can now assert visibility on elements below the fold without manually scrolling first — the driver scrolls them into view automatically, matching the legacy algorithm's behavior more closely and aligning with howcy.click()already works. Elements clipped byoverflow: hiddenancestors continue to be reported as hidden (matching the legacy algorithm and respecting the test author's clipping intent).pr-33736-demo.mp4
PR Tasks
cypress-documentation? cypress-io/cypress-documentation#6434type definitions?