Scrolling Elements into View with Cypress's scrollIntoView Command


Purpose

  • The scrollIntoView command in Cypress is used to programmatically scroll a web page to ensure a specific element is visible within the viewport. This is especially helpful for elements that are initially outside the visible area of the browser window.

Usage

  1. Locate the element
    Employ Cypress's element selection methods like cy.get(), cy.contains(), cy.xpath(), etc., to target the element you want to bring into view.

  2. Chain the scrollIntoView command
    Once you have a reference to the element, use the .scrollIntoView() method to initiate the scrolling action.

cy.get('.my-hidden-element').scrollIntoView();

This code will locate the element with the class my-hidden-element (assuming it's initially hidden) and scroll the page to make it visible within the viewport.

Optional Arguments

scrollIntoView accepts optional arguments to customize the scrolling behavior:

  • offset
    Allows you to control the final position of the element within the viewport. It's an object with properties:

    • top: The number of pixels from the top of the viewport where the element should be positioned after scrolling (positive displaces it down, negative displaces it up).
    • left: The number of pixels from the left of the viewport where the element should be positioned (positive moves it right, negative moves it left).
    cy.get('#nav').scrollIntoView({ offset: { top: 150 } }); // Scroll 150px below the nav element
    
  • duration
    Specifies the duration (in milliseconds) of the scrolling animation. This is useful if you want to control the speed of the scrolling action.

    cy.get('.next-page').scrollIntoView({ duration: 2000 }); // Scroll over 2 seconds
    
  • easing
    Controls the animation style of the scrolling. Valid options include:

    • 'linear': Uniformly scrolls from the current position to the target element.
    • 'easeInOut': (Default) Uses an easing curve for a smoother scrolling experience.

    Example:

    cy.get('#footer').scrollIntoView({ easing: 'linear' });
    

Important Considerations

  • Testing for visibility
    After scrolling, consider using cy.should('be.visible') to verify that the element is indeed visible within the viewport. This helps ensure your test is more robust.

  • Chaining commands after scrollIntoView
    Cypress recommends avoiding chaining commands directly after scrollIntoView because it might lead to unexpected behavior due to the asynchronous nature of scrolling. Instead, introduce a wait command (e.g., cy.wait(1000)) to ensure the element is fully visible before proceeding with further interactions.



Scrolling to an Element at the Bottom of the Page

cy.get('.footer-link').scrollIntoView(); // Scroll to the element with class 'footer-link'

Scrolling to an Element with a Specific Position

cy.get('#product-details').scrollIntoView({ offset: { top: -100 } }); // Scroll to '#product-details' 100px above its default position

Scrolling with a Linear Animation

cy.get('.modal-content').scrollIntoView({ easing: 'linear' }); // Scroll to '.modal-content' with a linear animation

Scrolling with a Custom Duration

cy.get('.long-article').scrollIntoView({ duration: 3000 }); // Scroll to '.long-article' over 3 seconds

Waiting for Scrolling to Finish Before Interaction

cy.get('#hidden-button').scrollIntoView();
cy.wait(1000); // Wait for scrolling to complete before interacting
cy.get('#hidden-button').click(); // Click the button after it's visible
cy.get('.hidden-element').scrollIntoView();
cy.get('.hidden-element').should('be.visible'); // Assert that the element is visible after scrolling


cy.scrollTo

  • Usage

    cy.scrollTo('bottom'); // Scroll to the bottom of the viewport
    cy.scrollTo('top');   // Scroll to the top of the viewport
    cy.scrollTo('right');   // Scroll to the right of the viewport (if the content is horizontally scrollable)
    // You can also specify exact coordinates:
    cy.scrollTo('center', { top: 200 }); // Scroll vertically to center the viewport 200px from the top
    
  • Purpose
    Similar to scrollIntoView, cy.scrollTo scrolls the viewport to a specific position. However, it offers more granular control over the scrolling behavior.

Advantages

  • Can be useful when you want to scroll to a specific position within the viewport, not necessarily bringing an element into view.
  • More control over scrolling behavior (e.g., scrolling to specific coordinates, horizontal scrolling).

Disadvantages

  • Doesn't guarantee an element will be visible after scrolling. You might need to combine it with visibility assertions.

User Actions

  • Purpose
    If your test aims to mimic user interactions, consider using Cypress commands that simulate user actions like:

    • cy.trigger('scroll', { top: 100 }); (Triggers a scroll event to a specific position)
    • cy.get('body').type('{pagedown}'); (Simulates pressing the Page Down key)

Advantages

  • More realistic test scenarios that mimic user behavior.

Disadvantages

  • May not be suitable for tests that require precise scrolling to specific elements.
  • Less control over the precise scrolling behavior.

Choosing the Right Option

The best approach depends on your testing needs:

  • Simulate user actions if you want to mimic realistic user interactions with scrolling.
  • Use cy.scrollTo if you require precise control over the scrolling position within the viewport (e.g., scrolling to specific coordinates).
  • Use scrollIntoView if you need to guarantee an element is visible after scrolling.