Skip to main content
Cypress App

scrollIntoView

Scroll the nearest scrollable container, or the window, until an element is in view.

It is unsafe to chain further commands that rely on the subject after .scrollIntoView().

Syntax​

.scrollIntoView()
.scrollIntoView(options)

Usage​

Correct Usage

cy.get('footer').scrollIntoView() // Scrolls 'footer' into view

Incorrect Usage

cy.scrollIntoView('footer') // Errors, cannot be chained off 'cy'
cy.window().scrollIntoView() // Errors, 'window' doesn't yield a DOM element
cy.get('li').scrollIntoView() // Errors, 'li' yields more than one element

Arguments​

options (Object)

Pass in an options object to change the default behavior of .scrollIntoView().

OptionDefaultDescription
duration0Time in ms to animate the scroll over, as a number or a numeric string such as '500'
easingswingEasing animation for the scroll: swing or linear (any other value throws an error)
logtrueDisplays the command in the Command Log
offset{top: 0, left: 0}Pixels to scroll past the element, or short of it when negative, to leave room above or to the left; a key left out defaults to 0
timeoutdefaultCommandTimeoutTime to wait for assertions chained after .scrollIntoView() to pass before timing out

Yields ​

  • .scrollIntoView() yields the same subject it was given.
  • It is unsafe to chain further commands that rely on the subject after .scrollIntoView().

Examples​

Scrolling​

cy.get('button#checkout').scrollIntoView()

Check that an element is in the viewport​

Visibility doesn't account for the viewport, so .should('be.visible') passes for an element that is scrolled out of view. To confirm the scroll worked, check the element's position instead. This checks that its top edge is inside the viewport.

cy.get('button#checkout').scrollIntoView()
cy.get('button#checkout')
.invoke('get', 0)
.invoke('getBoundingClientRect')
.its('top')
.should('be.within', 0, Cypress.config('viewportHeight'))

Scroll an item inside a scrollable container​

When the element sits inside a scrollable container, such as a results list, .scrollIntoView() scrolls that container to reach it, as described in Where the element lands after scrolling.

cy.get('[data-cy="results"] li').eq(40).scrollIntoView()
cy.get('[data-cy="results"]').its('0.scrollTop').should('be.greaterThan', 0)

Options​

Use linear easing animation to scroll​

cy.get('.next-page').scrollIntoView({ easing: 'linear' })

Animate the scroll to an element over 2000ms​

cy.get('footer').scrollIntoView({ duration: 2000 })

Scroll 150px past the top of an element​

cy.get('#nav').scrollIntoView({ offset: { top: 150, left: 0 } })

Leave room for a fixed header​

A negative offset stops short of the element, so it lands below a fixed header instead of underneath it.

cy.get('#pricing').scrollIntoView({ offset: { top: -80, left: 0 } })

Workflows​

Show a back-to-top button after scrolling​

Sticky headers, "back to top" buttons, and lazy-loaded images change as the page scrolls. Scroll to a point on the page, then assert on the change.

cy.get('footer').scrollIntoView()
cy.get('[data-cy="back-to-top"]').should('have.class', 'is-shown')

Notes​

Where the element lands after scrolling​

.scrollIntoView() scrolls the element's nearest scrollable ancestor, or the window when there isn't one, until the element's top-left corner lines up with the top-left of that container, as far as the container can scroll. Use the offset option to adjust where it lands. When the scrollable ancestor is a container inside the page, Cypress first scrolls that container into view, then scrolls the element within it.

Actionability​

.scrollIntoView() doesn't run the actionability checks that commands like .click() do. It scrolls an element even when the element is hidden, disabled, or covered by another element.

Skip .scrollIntoView() before action commands​

Action commands such as .click() and .type() scroll the element into view before acting on it, so a .scrollIntoView() in front of them adds nothing. The scrollBehavior option controls where the element lands, and setting it to false turns this scrolling off.

cy.get('#submit').scrollIntoView().click() // ❌ the scroll is redundant
cy.get('#submit').click() // ✅ .click() scrolls the element into view itself

Choosing between .scrollTo() and .scrollIntoView()​

.scrollTo() scrolls a container, either the window or a scrollable element, to a position. .scrollIntoView() scrolls whatever contains an element until that element is in view. To reach a specific item, use .scrollIntoView() on the item rather than .scrollTo() on its container.

cy.get('#feed').scrollTo('bottom') // scrolls the container itself
cy.get('#item-5').scrollIntoView() // scrolls until this item is in view

Compare where each call leaves the list:

The same eight-item list after each call: scrollTo('bottom') shows items 6 to 8; scrollIntoView() on Item 5 shows items 5 to 7.

Snapshots don't show scroll positions​

Snapshots don't capture scroll positions. To watch the scrolling, step through the commands with .pause() or watch the video of the test run.

Rules​

Requirements ​

  • .scrollIntoView() requires being chained off a command that yields a single DOM element. It throws an error when the subject contains more than one element.

Assertions ​

  • .scrollIntoView() runs once and is not retried. Assertions chained after .scrollIntoView() retry until they pass or time out. See Only queries are retried.

Timeouts ​

  • .scrollIntoView() can time out waiting for assertions you've added to pass.

Command Log​

Scroll a button into view inside a horizontal container

cy.get('#scroll-horizontal button').scrollIntoView()
cy.get('#scroll-horizontal').its('0.scrollLeft').should('be.greaterThan', 0)

The commands above display in the Command Log as:

Command Log rows for getting the button, scrolling it into view, and asserting the container's scrollLeft of 245 is above 0

Clicking the scrollIntoView command in the Command Log prints the following to the console:

DevTools console output for scrollIntoView, listing the command and the button it was applied to and scrolled

History​

VersionChanges
0.20.0.scrollIntoView() command added

See also​