JavaScript Element scroll Event

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
DOM event
Instance event

What You’ll Learn

The scroll event fires when an element has been scrolled. Learn addEventListener vs onscroll, scrollTop / scrollLeft, why handlers should be throttled, how it differs from wheel, and five try-it labs.

01

Kind

Instance event

02

Type

Event

03

When

Element was scrolled

04

Handler

onscroll

05

Bubbles?

No

06

Status

Baseline widely available

Introduction

scroll answers: “Did this element’s scroll position just change?” That covers overflow boxes, custom scroll panes, and (on document / window) the whole page.

Listen on the element that actually scrolls. Because the event does not bubble, a parent will not see a child’s scroll unless you attach the listener to that child.

💡
Beginner tip

MDN notes scroll can fire at a high rate. Keep handlers light, or throttle with setTimeout / requestAnimationFrame. To detect when scrolling finished, use the Element scrollend event.

Understanding scroll

An instance event that answers: “Did scroll offset change on this element?”

  • Trigger — user or script scrolled the element (scrollbar, keys, touch, scrollTo, …).
  • Event type — generic Event; read position from the element.
  • Does not bubble — attach to the scrolling element.
  • Not cancelable — you cannot stop scrolling with preventDefault() on scroll.
  • Baseline Widely available on MDN (since July 2015).

📝 Syntax

Use the event name with addEventListener, or set the handler property:

JavaScript
addEventListener("scroll", (event) => { });

onscroll = (event) => { };

Event type

A generic Event.

Handy element properties

PropertyMeaning
scrollTopVertical pixels scrolled from the top
scrollLeftHorizontal pixels scrolled from the left
scrollHeight / clientHeightContent height vs visible height (progress math)
scrollWidth / clientWidthContent width vs visible width

⚡ Throttle High-Rate Scroll

MDN’s Element examples use setTimeout to reset a status message after scrolling pauses. For continuous UI updates, a common pattern is:

  • Read scrollTop immediately in the listener.
  • Schedule heavy work once per frame with requestAnimationFrame.
  • Avoid layout thrashing (many reads/writes of size) inside the raw handler.

⚡ Quick Reference

GoalCode / note
Listenel.addEventListener("scroll", fn)
Handler propertyel.onscroll = fn
Positionel.scrollTop, el.scrollLeft
ThrottlesetTimeout / requestAnimationFrame
Finished?Element scrollend
MDN statusBaseline Widely available (Jul 2015)

🔍 At a Glance

Four facts to remember about scroll.

Event type
Event

Generic event

Means
offset changed

scrollTop/Left

Bubbles
false

Listen on target

Baseline
yes

Since Jul 2015

Examples Gallery

Examples follow MDN Element: scroll event. Scroll inside the small overflow boxes in each try-it lab.

📚 Getting Started

MDN listener patterns with a simple timeout reset.

Example 1 — Log scroll (MDN)

Detect scrolling inside an overflow box; reset the message after 1s.

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

element.addEventListener("scroll", (event) => {
  output.textContent = "Scroll event fired!";
  setTimeout(() => {
    output.textContent = "Waiting on scroll events...";
  }, 1000);
});
Try It Yourself

How It Works

The listener is on the scrolling div. The timeout shows MDN’s simple throttle-style reset.

Example 2 — onscroll Property (MDN)

Same idea using the handler property form.

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

element.onscroll = (event) => {
  output.textContent = "Element scroll event fired!";
  setTimeout(() => {
    output.textContent = "Waiting on scroll events...";
  }, 1000);
};
Try It Yourself

How It Works

Prefer addEventListener when you need multiple listeners or easy removal.

📈 Position, Throttle & Progress

Read offsets, batch work with rAF, and show scroll progress.

Example 3 — Log scrollTop / scrollLeft

Show the live scroll offsets while the box moves.

JavaScript
const box = document.getElementById("scroll-box");
const out = document.getElementById("out");

box.addEventListener("scroll", () => {
  out.textContent =
    "top=" + Math.round(box.scrollTop) +
    " left=" + Math.round(box.scrollLeft);
});
Try It Yourself

How It Works

The event itself is a plain Event—position lives on the element.

Example 4 — requestAnimationFrame Throttle

Read scroll immediately; paint once per animation frame.

JavaScript
const box = document.getElementById("scroll-box");
const out = document.getElementById("out");
let latestTop = 0;
let ticking = false;

function paint() {
  out.textContent = "rAF paint top=" + Math.round(latestTop);
  ticking = false;
}

box.addEventListener("scroll", () => {
  latestTop = box.scrollTop;
  if (!ticking) {
    requestAnimationFrame(paint);
    ticking = true;
  }
});
Try It Yourself

How It Works

Many scroll events may arrive between frames; only one paint runs per frame.

Example 5 — Scroll Progress %

Compute how far the user has scrolled through the content.

JavaScript
const box = document.getElementById("scroll-box");
const out = document.getElementById("out");

box.addEventListener("scroll", () => {
  const max = box.scrollHeight - box.clientHeight;
  const pct = max > 0 ? Math.round((box.scrollTop / max) * 100) : 0;
  out.textContent = "progress=" + pct + "%";
});
Try It Yourself

How It Works

scrollHeight - clientHeight is the maximum scrollTop for a vertical pane.

🚀 Common Use Cases

  • Reading position for sticky headers, shadows, or “back to top” buttons.
  • Scroll progress bars and reading indicators.
  • Lazy-loading content near the bottom of a pane.
  • Syncing custom scrollbars or mirrored panels.
  • Pairing continuous scroll updates with scrollend for final cleanup.

🔧 How It Works

1

Overflow content

Element can scroll (overflow, tall content, etc.).

Setup
2

Offset changes

User or script changes scrollTop / scrollLeft.

Input
3

scroll fires

Generic Event on that element; does not bubble.

Event
4

Update UI lightly

Read offsets; throttle paint; optionally wait for scrollend.

📝 Notes

Browser Support

scroll is marked Baseline Widely available on MDN (since July 2015). Logos use the shared browser-image-sprite.png sprite from this project. Attach listeners to the element that scrolls and keep handlers light.

Baseline · Widely available

Element scroll

Fires when an element’s scroll position changes; does not bubble; throttle high-rate handlers.

Full Widely available
Google Chrome Full support
Yes
Mozilla Firefox Full support
Yes
Apple Safari Full support
Yes
Microsoft Edge Full support
Yes
Opera Full support
Yes
Internet Explorer Supported (legacy)
Yes
scroll Baseline

Bottom line: Listen on the scrolling element, read scrollTop/scrollLeft, and throttle UI work. Use scrollend when you need the stop signal.

Conclusion

scroll is the standard signal that an element’s scroll offset changed. Attach it to the right target, read scrollTop / scrollLeft, and keep handlers light.

Continue with scrollend, scrollTop, scrollTo(), addEventListener(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Listen on the element that actually scrolls
  • Read scrollTop / scrollLeft from that element
  • Throttle or batch UI updates under fast scrolling
  • Use scrollend when you only care about the stop
  • Prefer addEventListener for multiple handlers

❌ Don’t

  • Expect scroll to bubble from children
  • Do heavy DOM work on every raw scroll event
  • Confuse wheel (intent) with scroll (position change)
  • Assume preventDefault on scroll can stop scrolling
  • Overwrite onscroll if you need multiple listeners

Key Takeaways

Knowledge Unlocked

Five things to remember about scroll

Offset changed—listen on the scroller, throttle the work.

5
Core concepts
📄02

Event

read scrollTop

API
03

No bubble

listen on target

Compare
04

Throttle

setTimeout / rAF

Perf
🎯05

Baseline

since Jul 2015

Status

❓ Frequently Asked Questions

It fires when an element has been scrolled—its scrollTop and/or scrollLeft changed. Listen on the element that actually scrolls (for example a div with overflow), not only on a parent.
No. MDN marks Element scroll as Baseline Widely available (since July 2015). It is not Deprecated, Experimental, or Non-standard.
A generic Event (not a specialized ScrollEvent). Read scroll position from the element via scrollTop, scrollLeft, and related properties.
No. Element scroll does not bubble, so a parent listener will not see a child’s scroll. Attach the listener to the scrolling element itself.
Scroll can fire at a very high rate. MDN’s examples use setTimeout (or requestAnimationFrame on Document scroll) so expensive work does not run on every single event.
MDN points to the Element scrollend event for detecting when scrolling has completed. Use scroll for continuous updates and scrollend for the final stop.
Did you know?

Turning a mouse wheel fires wheel even if nothing scrolls (for example at the end of a pane). scroll only fires when the scroll offset actually changes.

Next: scrollend

Detect when element scrolling has completed.

scrollend →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful