Skip to content

Commit

Permalink
docs(API): scrollend event fired when scrolling complete in Documen…
Browse files Browse the repository at this point in the history
…t and scrollable elements (mdn#22894)
  • Loading branch information
bsmth committed Dec 13, 2022
1 parent 59fc272 commit ad11fa0
Show file tree
Hide file tree
Showing 4 changed files with 322 additions and 37 deletions.
20 changes: 9 additions & 11 deletions files/en-us/web/api/document/scroll_event/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Document: scroll event'
title: "Document: scroll event"
slug: Web/API/Document/scroll_event
page-type: web-api-event
tags:
Expand All @@ -15,18 +15,18 @@ browser-compat: api.Document.scroll_event

{{APIRef}}

The **`scroll`** event fires when the document view has been scrolled. For element scrolling, see {{domxref("Element/scroll_event", "Element: scroll event")}}.

> **Note:** In iOS UIWebViews, `scroll` events are not fired while scrolling is taking place; they are only fired after the scrolling has completed. See [Bootstrap issue #16202](https://github.com/twbs/bootstrap/issues/16202). Safari and WKWebViews are not affected by this bug.
The **`scroll`** event fires when the document view has been scrolled.
To detect when scrolling has completed, see the {{domxref("Document/scrollend_event", "Document: scrollend event")}}.
For element scrolling, see {{domxref("Element/scroll_event", "Element: scroll event")}}.

## Syntax

Use the event name in methods like {{domxref("EventTarget.addEventListener", "addEventListener()")}}, or set an event handler property.

```js
addEventListener('scroll', (event) => {});
addEventListener("scroll", (event) => {});

onscroll = (event) => { };
onscroll = (event) => {};
```

## Event type
Expand All @@ -41,8 +41,6 @@ Since `scroll` events can fire at a high rate, the event handler shouldn't execu

Note, however, that input events and animation frames are fired at about the same rate, and therefore the optimization below is often unnecessary. This example optimizes the `scroll` event for `requestAnimationFrame`.

<!--Reference: http://www.html5rocks.com/en/tutorials/speed/animations/ no longer exists. -->

```js
let lastKnownScrollPosition = 0;
let ticking = false;
Expand All @@ -51,7 +49,7 @@ function doSomething(scrollPos) {
// Do something with the scroll position
}

document.addEventListener('scroll', (e) => {
document.addEventListener("scroll", (event) => {
lastKnownScrollPosition = window.scrollY;

if (!ticking) {
Expand All @@ -65,8 +63,6 @@ document.addEventListener('scroll', (e) => {
});
```

See more, similar examples on the [`resize`](/en-US/docs/Web/API/Window/resize_event) event page.

## Specifications

{{Specifications}}
Expand All @@ -77,4 +73,6 @@ See more, similar examples on the [`resize`](/en-US/docs/Web/API/Window/resize_e

## See also

- [Document: `scrollend` event](/en-US/docs/Web/API/Document/scrollend_event)
- [Element: `scroll` event](/en-US/docs/Web/API/Element/scroll_event)
- [Element: `scrollend` event](/en-US/docs/Web/API/Element/scrollend_event)
157 changes: 157 additions & 0 deletions files/en-us/web/api/document/scrollend_event/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
title: "Document: scrollend event"
slug: Web/API/Document/scrollend_event
page-type: web-api-event
browser-compat: api.Document.scrollend_event
---

{{APIRef}}

The **`scrollend`** event fires when the document view has completed scrolling.
Scrolling is considered completed when the scroll position has no more pending updates and the user has completed their gesture.

Scroll position updates include smooth or instant mouse wheel scrolling, keyboard scrolling, scroll-snap events, or other APIs and gestures which cause the scroll position to update.
User gestures like touch panning or trackpad scrolling aren't complete until pointers or keys have released.
If the scroll position did not change, then no scrollend event fires.

For detecting when scrolling inside an element is complete, see {{domxref("Element/scrollend_event", "Element: scrollend event")}}.

## Syntax

Use the event name in methods like {{domxref("EventTarget.addEventListener", "addEventListener()")}}, or set an event handler property.

```js
addEventListener("scrollend", (event) => {});

onscrollend = (event) => {};
```

## Event type

A generic {{domxref("Event")}}.

## Examples

### Using Document `scrollend` with an event listener

The following example shows how to use the `scrollend` event with an event listener to detect when the user has stopped scrolling the document.
In the example, there is content in the embedded iframe that is taller and wider than the iframe itself, so scrolling within the iframe in both directions is possible.
When the user stops scrolling, the `scrollend` event fires:

```css hidden
* {
margin: 10px;
}

.box-wrapper {
width: 900px;
border: 4px dotted;
}

.box {
height: 100px;
width: 100px;
display: block;
border: 4px dotted;
border-radius: 10px;
}

#output {
text-align: center;
font-size: 1.2em;
position: sticky;
bottom: 0;
}
```

```html
<div class="box-wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<p id="output">Waiting on scroll events...</p>
```

```js
const output = document.querySelector("p#output");

document.addEventListener("scroll", (event) => {
output.innerHTML = `Document scroll event fired!`;
});

document.addEventListener("scrollend", (event) => {
output.innerHTML = `Document scrollend event fired!`;
});
```

{{EmbedLiveSample("Using_document_scrollend_with_an_event_listener", "100%", 200)}}

### Using `onscrollend` event handler property

The following example shows how to use the `scrollend` event handler property to detect when the user has stopped scrolling the document.
In the example, there is content in the embedded iframe that is taller and wider than the iframe itself, so scrolling within the iframe in both directions is possible.
This builds on the first example, but uses `document.onscrollend` instead of an event listener:

```css hidden
* {
margin: 10px;
}

.box-wrapper {
width: 900px;
border: 4px dotted;
}

.box {
height: 100px;
width: 100px;
display: block;
border: 4px dotted;
border-radius: 10px;
}

#output {
text-align: center;
font-size: 1.2em;
position: sticky;
bottom: 0;
}
```

```html
<div class="box-wrapper">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
<p id="output">Waiting on scroll events...</p>
```

```js
document.onscroll = (event) => {
output.innerHTML = "Document scroll event fired!";
};

document.onscrollend = (event) => {
output.innerHTML = "Document scrollend event fired!";
};
```

{{EmbedLiveSample("Using_scrollend_with_an_event_handler_property", "100%", 200)}}

## Specifications

{{Specifications}}

## Browser compatibility

{{Compat}}

## See also

- [Document `scroll` event](/en-US/docs/Web/API/Document/scroll_event)
- [Element `scrollend` event](/en-US/docs/Web/API/Element/scrollend_event)
- [Element `scroll` event](/en-US/docs/Web/API/Element/scroll_event)
79 changes: 53 additions & 26 deletions files/en-us/web/api/element/scroll_event/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: 'Element: scroll event'
title: "Element: scroll event"
slug: Web/API/Element/scroll_event
page-type: web-api-event
tags:
Expand All @@ -14,17 +14,16 @@ browser-compat: api.Element.scroll_event
{{APIRef}}

The **`scroll`** event fires when an element has been scrolled.

> **Note:** In iOS UIWebViews, `scroll` events are not fired while scrolling is taking place; they are only fired after the scrolling has completed. See [Bootstrap issue #16202](https://github.com/twbs/bootstrap/issues/16202). Safari and WKWebViews are not affected by this bug.
To detect when scrolling has completed, see the {{domxref("Element/scrollend_event", "Element: scrollend event")}}.

## Syntax

Use the event name in methods like {{domxref("EventTarget.addEventListener", "addEventListener()")}}, or set an event handler property.

```js
addEventListener('scroll', (event) => {});
addEventListener("scroll", (event) => {});

onscroll = (event) => { };
onscroll = (event) => {};
```

## Event type
Expand All @@ -33,37 +32,63 @@ A generic {{domxref("Event")}}.

## Examples

### Scroll event throttling
The following examples show how to use the `scroll` event with an event listener and with the `onscroll` event handler property.
The {{DOMxRef("setTimeout()")}} method is used to throttle the event handler because `scroll` events can fire at a high rate.
For additional examples that use {{DOMxRef("Window.requestAnimationFrame()", "requestAnimationFrame()")}}, see the {{domxref("Document/scroll_event", "Document: scroll event")}} page.

Since `scroll` events can fire at a high rate, the event handler shouldn't execute computationally expensive operations such as DOM modifications. Instead, it is recommended to throttle the event using {{DOMxRef("Window.requestAnimationFrame()", "requestAnimationFrame()")}}, {{DOMxRef("setTimeout()")}}, or a {{DOMxRef("CustomEvent")}}, as follows.
### Using `scroll` with an event listener

Note, however, that input events and animation frames are fired at about the same rate, and therefore the optimization below is often unnecessary. This example optimizes the `scroll` event for `requestAnimationFrame`.
The following example shows how to use the `scroll` event to detect when the user is scrolling inside an element:

<!--Reference: http://www.html5rocks.com/en/tutorials/speed/animations/ no longer exists. -->
```html
<div
id="scroll-box"
style="overflow: scroll; height: 100px; width: 100px; float: left;">
<p style="height: 200px; width: 200px;">Scroll me!</p>
</div>
<p style="text-align: center;" id="output">Waiting on scroll events...</p>
```

```js
let last_known_scroll_position = 0;
let ticking = false;
const element = document.querySelector("div#scroll-box");
const output = document.querySelector("p#output");

element.addEventListener("scroll", (event) => {
output.innerHTML = "Scroll event fired!";
setTimeout(() => {
output.innerHTML = "Waiting on scroll events...";
}, 1000);
});
```

function doSomething(scroll_pos) {
// Do something with the scroll position
}
{{EmbedLiveSample("Using_scroll_with_an_event_listener", "100%", 120)}}

window.addEventListener('scroll', (e) => {
last_known_scroll_position = window.scrollY;
### Using `onscroll` event handler property

if (!ticking) {
window.requestAnimationFrame(() => {
doSomething(last_known_scroll_position);
ticking = false;
});
The following example shows how to use the `onscroll` event handler property to detect when the user is scrolling:

ticking = true;
}
});
```html
<div
id="scroll-box"
style="overflow: scroll; height: 100px; width: 100px; float: left;">
<p style="height: 200px; width: 200px;">Scroll me!</p>
</div>
<p id="output" style="text-align: center;">Waiting on scroll events...</p>
```

```js
const element = document.querySelector("div#scroll-box");
const output = document.querySelector("p#output");

element.onscroll = (event) => {
output.innerHTML = "Element scroll event fired!";
setTimeout(() => {
output.innerHTML = "Waiting on scroll events...";
}, 1000);
};
```

> **Note:** You can find more examples on the {{domxref("Window/resize_event", "resize")}} event page.
{{EmbedLiveSample("Using_onscroll_event_handler_property", "100%", 120)}}

## Specifications

Expand All @@ -75,4 +100,6 @@ window.addEventListener('scroll', (e) => {

## See also

- Document: {{domxref("Document/scroll_event", "scroll")}} event
- [Element `scrollend` event](/en-US/docs/Web/API/Element/scrollend_event)
- [Document `scroll` event](/en-US/docs/Web/API/Document/scroll_event)
- [Document `scrollend` event](/en-US/docs/Web/API/Document/scrollend_event)

0 comments on commit ad11fa0

Please sign in to comment.