The scroll steps move the page - or a specific scrollable element - vertically and horizontally so the right content is on screen before you assert on it or interact with it. They cover relative movement (down, up, left, right, by a pixel amount), absolute movement (to the top, bottom, start, or end), and the same set of movements scoped to any element identified by a CSS selector, such as an off-canvas panel or an overflow container.
You rarely need a scroll step just to click or assert: webship-js action steps use Playwright locators, which auto-scroll the target into view, and the framework's BBR smart waits handle timing. Reach for explicit scrolling when the scroll itself is the behavior under test - lazy-loading and infinite-scroll lists, sticky or shrinking headers, scroll-triggered animations, "back to top" buttons - or when you want a screenshot to show a particular region of a long page.
Implementation notes worth knowing: relative steps default to 350 pixels when no number is given; the page-level "scroll to the bottom" step also scrolls every nested scrollable container (any element whose overflow-y is scroll or auto) to its own bottom and dispatches a bubbling scroll event on each, so scroll-listening JavaScript fires just as it would for a real user. The element-scoped top/bottom variants dispatch that scroll event too. Every phrasing accepts I scroll, we scroll, scrolling, or no prefix at all, and the words the / of the page are optional.
Quick reference
| Step | What it does |
|---|---|
And I scroll down | Scroll the page down by a custom number of pixels (default 350). |
And I scroll up | Scroll the page up by a custom number of pixels (default 350). |
When I scroll to top | Scroll to the very top of the current page. |
When I scroll to the bottom | Scroll to the bottom of the page (including nested scrollable containers). |
When I scroll to top of "#off-canvas" | Scroll a specific element to its top. |
When I scroll to bottom of "#off-canvas" | Scroll a specific element to its bottom. |
And I scroll right | Scroll the page right by a custom number of pixels (default 350). |
And I scroll left | Scroll the page left by a custom number of pixels (default 350). |
When I scroll to start | Scroll to the horizontal origin of the page. |
When I scroll to the end | Scroll to the horizontal maximum of the page. |
When I scroll to start of "#off-canvas" | Scroll a specific element to its horizontal start. |
When I scroll to end of "#off-canvas" | Scroll a specific element to its horizontal end. |
Steps in detail
And I scroll down / And I scroll up
Scrolls the window vertically by 350 pixels, or by the number you append: When I scroll down 800, And we scroll up 300, When scrolling down 1200. Relative scrolling is ideal for testing content that loads or animates as the user moves through the page in increments.
Given I am on "/test--when--i-scroll-functionality.html"
When I scroll down 500
Then I should see "Custom scroll down works"
When I scroll to top / When I scroll to the bottom
Jumps to the absolute top (window.scrollTo(0, 0)) or bottom of the document. The bottom variant additionally walks the DOM for nested scrollable containers, scrolls each to its own bottom, and fires a bubbling scroll event on it - so infinite-scroll widgets inside overflow panes load their next batch as well. Optional wording: to the top, to the bottom of the page.
Given I am on "/test--when--i-scroll-functionality.html"
When I scroll to the bottom
And I scroll to top
Then I should see "Scroll to top works"
When I scroll to top of "#off-canvas" / When I scroll to bottom of "#off-canvas"
Scopes the vertical scroll to one element found by CSS selector - its scrollTop is set to 0 or to its full scrollHeight, and a bubbling scroll event is dispatched so listeners react. Use these for off-canvas menus, chat panes, modal bodies, and any overflow: auto region whose internal position matters.
When I scroll to bottom of "#scrollable-container"
And I scroll to top of "#scrollable-container"
Then I should see "Element scroll to top works"
And I scroll right / And I scroll left
The horizontal counterparts of down/up: scroll the window sideways by 350 pixels or a custom amount (When I scroll right 1000). Useful for wide tables, carousels, and horizontally scrolling layouts.
Given I am on "/test--when--i-scroll-left-right-functionality.html"
When I scroll right 750
And I scroll left 300
When I scroll to start / When I scroll to the end
Jumps to the horizontal origin or the horizontal maximum (document.body.scrollWidth) of the page while keeping the current vertical position. Wording is flexible: to the start, to end of the page.
When I scroll to the end
Then I should see "Rightmost column"
When I scroll to start
When I scroll to start of "#off-canvas" / When I scroll to end of "#off-canvas"
Horizontal scrolling scoped to a single element: scrollLeft is set to 0 or to the element's full scrollWidth. Reach for these when testing horizontally scrollable components such as image strips, kanban boards, or data tables inside a fixed-width pane.
When I scroll to end of "#timeline"
Then I should see "December"
When I scroll to start of "#timeline"
Complete example
Adapted from tests/features/test--when--i-scroll.feature, which runs against the fixture page examples/test--when--i-scroll-functionality.html:
Feature: Complete scrolling functionality test
As a tester,
I want to test all scrolling step definitions to ensure they work correctly.
Scenario: Test basic scroll down functionality
Given I am on "/test--when--i-scroll-functionality.html"
When I scroll down
Then I should see "Basic scroll down works"
Scenario: Test scroll up with custom value
Given I am on "/test--when--i-scroll-functionality.html"
When I scroll to the bottom
And I scroll up 300
Then I should see "Custom scroll up works"
Scenario: Test scroll to bottom of element
Given I am on "/test--when--i-scroll-functionality.html"
When I scroll to bottom of "#scrollable-container"
Then I should see "Element scroll to bottom works"
Tips
- Click and assertion steps auto-scroll their target into view - add explicit scroll steps only when the scrolling itself triggers behavior you want to test.
- After a scroll that triggers lazy loading, the following
Then I should see ...assertion auto-waits for the content, so no fixed sleep is needed. - Combine with the screenshot steps to capture below-the-fold regions at a known scroll position, e.g.
When I scroll down 800thenThen I save screenshot. - The scoped variants take a raw CSS selector in quotes; to scroll named components from the selector registry, resolve them to their CSS first.