Skip to content

Commit

Permalink
docs: add section explaining scrolling (#30719)
Browse files Browse the repository at this point in the history
Fixes #30643.
  • Loading branch information
dgozman committed May 9, 2024
1 parent 7a0c773 commit a5d384c
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 3 deletions.
2 changes: 2 additions & 0 deletions docs/src/api/class-elementhandle.md
Original file line number Diff line number Diff line change
Expand Up @@ -789,6 +789,8 @@ completely visible as defined by
Throws when `elementHandle` does not point to an element
[connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.

See [scrolling](../input.md#scrolling) for alternative ways to scroll.

### option: ElementHandle.scrollIntoViewIfNeeded.timeout = %%-input-timeout-%%
* since: v1.8

Expand Down
2 changes: 2 additions & 0 deletions docs/src/api/class-locator.md
Original file line number Diff line number Diff line change
Expand Up @@ -1972,6 +1972,8 @@ This method waits for [actionability](../actionability.md) checks, then tries to
completely visible as defined by
[IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)'s `ratio`.

See [scrolling](../input.md#scrolling) for alternative ways to scroll.

### option: Locator.scrollIntoViewIfNeeded.timeout = %%-input-timeout-%%
* since: v1.14

Expand Down
2 changes: 1 addition & 1 deletion docs/src/api/class-mouse.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Dispatches a `mouseup` event.
## async method: Mouse.wheel
* since: v1.15

Dispatches a `wheel` event.
Dispatches a `wheel` event. This method is usually used to manually scroll the page. See [scrolling](../input.md#scrolling) for alternative ways to scroll.

:::note
Wheel events may cause scrolling if they are not handled, and this method does not
Expand Down
103 changes: 103 additions & 0 deletions docs/src/input.md
Original file line number Diff line number Diff line change
Expand Up @@ -757,3 +757,106 @@ await page.Mouse.UpAsync();
:::note
If your page relies on the `dragover` event being dispatched, you need at least two mouse moves to trigger it in all browsers. To reliably issue the second mouse move, repeat your [`method: Mouse.move`] or [`method: Locator.hover`] twice. The sequence of operations would be: hover the drag element, mouse down, hover the drop element, hover the drop element second time, mouse up.
:::

## Scrolling

Most of the time, Playwright will automatically scroll for you before doing any actions. Therefore, you do not need to scroll explicitly.

```js
// Scrolls automatically so that button is visible
await page.getByRole('button').click();
```

```java
// Scrolls automatically so that button is visible
page.getByRole(AriaRole.BUTTON).click();
```

```python async
# Scrolls automatically so that button is visible
await page.get_by_role("button").click()
```

```python sync
# Scrolls automatically so that button is visible
page.get_by_role("button").click()
```

```csharp
// Scrolls automatically so that button is visible
await page.GetByRole(AriaRole.Button).ClickAsync();
```

However, in rare cases you might need to manually scroll. For example, you might want to force an "infinite list" to load more elements, or position the page for a specific screenshot. In such a case, the most reliable way is to find an element that you want to make visible at the bottom, and scroll it into view.

```js
// Scroll the footer into view, forcing an "infinite list" to load more content
await page.getByText('Footer text').scrollIntoViewIfNeeded();
```

```java
// Scroll the footer into view, forcing an "infinite list" to load more content
page.getByText("Footer text").scrollIntoViewIfNeeded();
```

```python async
# Scroll the footer into view, forcing an "infinite list" to load more content
await page.get_by_text("Footer text").scroll_into_view_if_needed()
```

```python sync
# Scroll the footer into view, forcing an "infinite list" to load more content
page.get_by_text("Footer text").scroll_into_view_if_needed()
```

```csharp
// Scroll the footer into view, forcing an "infinite list" to load more content
await page.GetByText("Footer text").ScrollIntoViewIfNeededAsync();
```

If you would like to control the scrolling more precisely, use [`method: Mouse.wheel`] or [`method: Locator.evaluate`]:

```js
// Position the mouse and scroll with the mouse wheel
await page.getByTestId('scrolling-container').hover();
await page.mouse.wheel(0, 10);

// Alternatively, programmatically scroll a specific element
await page.getByTestId('scrolling-container').evaluate(e => e.scrollTop += 100);
```

```java
// Position the mouse and scroll with the mouse wheel
page.getByTestId("scrolling-container").hover();
page.mouse.wheel(0, 10);

// Alternatively, programmatically scroll a specific element
page.getByTestId("scrolling-container").evaluate("e => e.scrollTop += 100");
```

```python async
# Position the mouse and scroll with the mouse wheel
await page.get_by_test_id("scrolling-container").hover()
await page.mouse.wheel(0, 10)

# Alternatively, programmatically scroll a specific element
await page.get_by_test_id("scrolling-container").evaluate("e => e.scrollTop += 100")
```

```python sync
# Position the mouse and scroll with the mouse wheel
page.get_by_test_id("scrolling-container").hover()
page.mouse.wheel(0, 10)

# Alternatively, programmatically scroll a specific element
page.get_by_test_id("scrolling-container").evaluate("e => e.scrollTop += 100")
```

```csharp
// Position the mouse and scroll with the mouse wheel
await page.GetByTestId("scrolling-container").HoverAsync();
await page.Mouse.WheelAsync(0, 10);

// Alternatively, programmatically scroll a specific element
await page.GetByTestId("scrolling-container").EvaluateAsync("e => e.scrollTop += 100");
```
7 changes: 6 additions & 1 deletion packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10374,6 +10374,8 @@ export interface ElementHandle<T=Node> extends JSHandle<T> {
*
* Throws when `elementHandle` does not point to an element
* [connected](https://developer.mozilla.org/en-US/docs/Web/API/Node/isConnected) to a Document or a ShadowRoot.
*
* See [scrolling](https://playwright.dev/docs/input#scrolling) for alternative ways to scroll.
* @param options
*/
scrollIntoViewIfNeeded(options?: {
Expand Down Expand Up @@ -12574,6 +12576,8 @@ export interface Locator {
* This method waits for [actionability](https://playwright.dev/docs/actionability) checks, then tries to scroll element into view, unless
* it is completely visible as defined by
* [IntersectionObserver](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API)'s `ratio`.
*
* See [scrolling](https://playwright.dev/docs/input#scrolling) for alternative ways to scroll.
* @param options
*/
scrollIntoViewIfNeeded(options?: {
Expand Down Expand Up @@ -18649,7 +18653,8 @@ export interface Mouse {
}): Promise<void>;

/**
* Dispatches a `wheel` event.
* Dispatches a `wheel` event. This method is usually used to manually scroll the page. See
* [scrolling](https://playwright.dev/docs/input#scrolling) for alternative ways to scroll.
*
* **NOTE** Wheel events may cause scrolling if they are not handled, and this method does not wait for the scrolling
* to finish before returning.
Expand Down
1 change: 0 additions & 1 deletion utils/build/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,6 @@ onChanges.push({
'packages/playwright-core/src/server/chromium/protocol.d.ts',
],
mustExist: [
'packages/playwright-core/lib/server/deviceDescriptors.js',
'packages/playwright-core/lib/server/deviceDescriptorsSource.json',
],
script: 'utils/generate_types/index.js',
Expand Down

0 comments on commit a5d384c

Please sign in to comment.