👀 Live Preview
Scroll this page — your distance from the top updates below:
Scroll position: 0 px from top

The onscroll attribute is an inline event handler for the scroll event. It runs JavaScript when the user scrolls inside a scrollable element — vertically or horizontally. Use it on containers with overflow: auto or overflow: scroll to react to scroll position, update labels, lazy-load content, or build effects like sticky headers. Read element.scrollTop or window.scrollY inside your handler. For whole-page scroll, prefer window.addEventListener("scroll", …). Throttle heavy work because scroll fires very often. For “when this section enters the viewport,” consider IntersectionObserver instead.
Inline JS.
Position change.
Scrollable div.
Pixels scrolled.
Performance.
Preferred way.
onscroll AttributeThe primary purpose of onscroll is to execute JavaScript when scroll position changes inside an element — so you can respond to user scroll actions and create dynamic experiences such as parallax effects, progress indicators, infinite lists, or lazy-loaded images.
The scroll event fires on the element whose content moved. For a scrollable <div>, put onscroll on that div. For the entire page, attach the handler to window in JavaScript rather than relying on <body onscroll> alone.
onscroll only fires when an element actually scrolls. A plain <div> with no overflow will never trigger it — add overflow: auto and content taller than the box.
Set onscroll on a scrollable element or assign element.onscroll in JavaScript:
<div id="panel" style="height:200px;overflow:auto" onscroll="handleScroll()">
…
</div>
<script>
panel.onscroll = handleScroll;
window.addEventListener("scroll", handleScroll, { passive: true });
</script>scroll event fires.auto, scroll, overlay).element.onscroll in script.element.scrollTop / scrollLeft for container position; window.scrollY for page scroll.addEventListener("scroll", handler, { passive: true }).IntersectionObserver.The onscroll attribute accepts a string of JavaScript code:
onscroll="handleScroll()" — Call a named function.onscroll="updateProgress()" — Update a scroll progress bar.element.onscroll = () => { … } — property assignment.var timer;
function handleScroll() {
clearTimeout(timer);
timer = setTimeout(function () {
status.textContent =
"Scrolled " + Math.round(window.scrollY) + " px from top";
}, 50);
}
window.addEventListener("scroll", handleScroll, { passive: true });| Property / API | When it runs | Notes |
|---|---|---|
scroll | Scroll position changes | onscroll |
element.scrollTop | Read anytime | Vertical px inside container |
window.scrollY | Read anytime | Page scroll from top |
element.scrollHeight | Read anytime | Total scrollable height |
IntersectionObserver | Element enters viewport | Lazy load, reveal on scroll |
| Target | Supported? | Notes |
|---|---|---|
<div>, <section> with overflow | Yes | Primary inline use — scrollable containers |
<textarea>, <iframe> | Yes | Native scrollable elements |
window | Yes (JS) | Page scroll via addEventListener |
<body> | Partial | Prefer window for document scroll |
| Non-scrollable elements | No | No overflow — no scroll event |
onscroll vs onwheel vs IntersectionObserver| API | What it watches | Typical use |
|---|---|---|
onscroll | Scroll position change | Progress bars, parallax, scroll labels |
onwheel | Mouse wheel / trackpad input | Custom zoom, horizontal carousels |
IntersectionObserver | Element visibility in viewport | Lazy loading, animate on reveal |
CSS position: sticky | Sticky positioning | Sticky headers without JS |
Scrollable div with inline handler, dynamic assignment, and a throttled page-scroll progress label.
Scroll this page — your distance from the top updates below:
Scroll position: 0 px from top
Detect scrolling inside a box with overflow: auto:
<div id="panel"
style="height:150px;overflow:auto;border:1px solid #ccc"
onscroll="showScroll()">
<div style="height:500px">
<p>Scroll inside this box.</p>
</div>
</div>
<p id="out"></p>
<script>
function showScroll() {
var panel = document.getElementById("panel");
document.getElementById("out").textContent =
"Scrolled " + panel.scrollTop + " px";
}
</script>When the user scrolls inside the div, the browser fires scroll on that element. The inline attribute calls showScroll(), which reads scrollTop — pixels scrolled from the top of the container.
Assign the handler on an element at runtime:
<script>
document.getElementById("dynamicElement").onscroll = function () {
log.textContent = "Scrolling inside the box!";
};
</script>Assigning element.onscroll is equivalent to the inline attribute for that element. Use this when you attach the handler after the DOM loads or based on user interaction.
Track how far the user has scrolled down the page without running heavy code on every pixel:
var timer;
window.addEventListener("scroll", function () {
clearTimeout(timer);
timer = setTimeout(function () {
var y = window.scrollY;
var max = document.documentElement.scrollHeight - window.innerHeight;
var pct = max > 0 ? Math.round((y / max) * 100) : 0;
status.textContent = "Page scroll: " + pct + "% (" + Math.round(y) + " px)";
}, 50);
}, { passive: true });Scroll can fire dozens of times per second. A 50ms throttle batches updates so your UI stays smooth on mobile devices.
prefers-reduced-motion before parallax or scroll-driven animations.Wheel, touch, or keys.
onscroll runs.
scrollTop / scrollY.
Progress, lazy load, effects.
The scroll event and onscroll handler are supported in all modern browsers, including Internet Explorer 9+.
onscroll supportAll major browsers fire scroll when scrollable content moves.
Bottom line: Reliable for scroll handling in all modern browsers — throttle handlers for smooth performance.
{ passive: true } with addEventListener for page scrollonscrollIntersectionObserver for lazy loading imagesprefers-reduced-motion for scroll animationsonscroll on elements that cannot scrollconsole.log alone in tutorials — show visible feedbackonwheel (input) with onscroll (position change)The onscroll attribute runs JavaScript when scroll position changes inside a scrollable element — useful for progress bars, lazy loading, parallax effects, and dynamic UI updates tied to scroll.
Throttle your handlers, use addEventListener with { passive: true } for page scroll, and reach for IntersectionObserver when you only need to know if an element is visible in the viewport.
onscrollBookmark these before wiring scroll logic.
Scrollable box.
ScopePerformance.
PatternRead px.
APILazy load.
PreferPosition vs input.
Gotchascroll event fires — when scroll position changes inside a scrollable element or on the page.overflow: auto with content taller than the box. Otherwise the event never fires.onwheel responds to wheel/trackpad input. onscroll fires when scroll position actually changes — including keyboard and scrollbar drag.addEventListener("scroll", handler, { passive: true }) is preferred in production — easier to throttle and attach multiple listeners.Practice the onscroll attribute with scrollable containers and throttled page scroll in the Try It editor.
5 people found this page helpful