jQuery .scroll() Method

Beginner
⚠️ Deprecated since 3.3
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Browser events

What You’ll Learn

The .scroll() method is jQuery’s legacy shorthand for binding and triggering the scroll event on the window or overflow elements. This tutorial covers .scroll(handler) since 1.0, .scroll(eventData, handler) since 1.4.3, no-argument .scroll() as a trigger, migration to .on("scroll") and .trigger("scroll"), why the binding form is deprecated since jQuery 3.3 but still works in 3.x, and how it differs from .scrollTop(). See the jQuery scroll event tutorial for the modern API.

01

.scroll(fn)

Bind handler

02

eventData

Since 1.4.3

03

.scroll()

Trigger event

04

.on()

Modern bind

05

.trigger()

Modern fire

06

Deprecated

Since 3.3

Introduction

Before jQuery 1.7 unified events with .on() and .off(), every common event had a matching shorthand — .scroll(), .resize(), .click(), and more. The .scroll() method let you react to scrolling in one short call: $(window).scroll(function(){ updateProgress(); }). It remains in jQuery 3.x for backward compatibility but is marked deprecated since 3.3 — unlike .error(), which was removed in jQuery 3.0.

Understanding .scroll() matters when reading older infinite-scroll, sticky-header, and chat-panel tutorials in legacy codebases. The method does two distinct jobs: with a function argument it binds; with no arguments it triggers. Modern jQuery splits those roles explicitly — .on("scroll", handler) for binding and .trigger("scroll") for firing. Do not confuse this event shorthand with .scrollTop(), which reads or sets scroll position.

⚠️
Bind on window or overflow elements

The scroll event fires on the element whose content moves — typically $(window) for page scroll, or a container with overflow: auto or overflow: scroll such as $("#panel"). Bind on the element whose scrollTop actually changes. Throttle expensive work inside handlers because scroll can fire many times per second.

Understanding the .scroll() Method

The official jQuery API describes .scroll() as a way to bind an event handler to the scroll event, or trigger that event on an element. When you pass a handler, jQuery registers it on each matched element and calls it when the user scrolls — the same scroll event that .on("scroll") handles today. Bind on $(window) for page-level scroll or on overflow containers for local scroll.

When you call .scroll() with no arguments, jQuery synthetically fires the scroll event on each matched element. Bound handlers run once per call. This trigger behavior is equivalent to .trigger("scroll"). It does not change scroll position — use .scrollTop() for that.

⚠️
Deprecated since jQuery 3.3

Do not use .scroll(handler) or .scroll(eventData, handler) in new code. Replace them with .on("scroll", handler) or .on("scroll", eventData, handler). Replace no-argument .scroll() with .trigger("scroll"). Unlike .error() (removed in 3.0), .scroll() still works in jQuery 3.x. For throttling, progress bars, and the full modern scroll workflow, read the jQuery scroll event tutorial.

📝 Syntax

The .scroll() method has three signatures from the official jQuery API. The binding forms are deprecated; the trigger form remains valid but .trigger("scroll") is preferred:

1. Bind a handler — .scroll( handler ) (since 1.0, deprecated 3.3)

jQuery
.scroll( handler )
  • handler — function executed each time scroll fires: function( event ) { ... }.
  • Returns the jQuery object for chaining.
  • Bind on $(window) for page scroll or on overflow elements for container scroll.
  • Modern replacement: .on( "scroll", handler ).

2. Bind with eventData — .scroll( [eventData], handler ) (since 1.4.3, deprecated 3.3)

jQuery
.scroll( [eventData], handler )
  • eventData — optional object available in the handler as event.data.
  • Modern replacement: .on( "scroll", eventData, handler ).

3. Trigger the event — .scroll() (since 1.0)

jQuery
.scroll()
  • No arguments — triggers scroll on every matched element.
  • Runs bound scroll handlers.
  • Preferred replacement: .trigger( "scroll" ).

Official jQuery API migration note

jQuery
// Deprecated binding
$( window ).scroll( function() {
  alert( "Handler for `scroll` called." );
} );

// Modern binding
$( window ).on( "scroll", function() {
  alert( "Handler for `scroll` called." );
} );

// Deprecated trigger
$( window ).scroll();

// Modern trigger
$( window ).trigger( "scroll" );

Return value

  • All .scroll() signatures return the original jQuery object for chaining.
  • Handler return values are ignored unless you use return false (equivalent to preventDefault() + stopPropagation()).

⚡ Quick Reference

GoalLegacy (.scroll)Modern replacement
Bind scroll handler on window$(window).scroll(fn)$(window).on("scroll", fn)
Bind on overflow container$("#panel").scroll(fn)$("#panel").on("scroll", fn)
Pass data to handler$(window).scroll({ threshold: 100 }, fn)$(window).on("scroll", { threshold: 100 }, fn)
Trigger scroll programmatically$("#target").scroll()$("#target").trigger("scroll")
Read scroll position$(window).scrollTop() — not an event API
Set scroll position$("#panel").scrollTop(200) — does not bind handlers
Remove scroll handlers$(window).off("scroll")$(window).off("scroll")
Throttled progress updateWrap body in throttle — scroll fires far more often than resize

📋 .scroll() vs .on("scroll") vs .trigger("scroll") vs .scrollTop()

Four related APIs — know which one binds, which one fires, and which one reads or sets position.

.scroll()
deprecated

Legacy bind (.scroll(fn)) or trigger (.scroll()) on window or overflow elements — use modern APIs for new code

.on("scroll")
bind

Modern binding since 1.7 — supports eventData; preferred for progress bars and lazy-load triggers

.trigger("scroll")
fire

Programmatically run handlers — clearer than no-arg .scroll()

.scrollTop()
position

Gets or sets vertical scroll pixels — not an event listener; pair with .on("scroll") to react to changes

Examples Gallery

Five examples cover binding on $(window) and overflow elements, eventData thresholds, triggering, migration from .scroll() to .on("scroll"), and throttling inside a legacy handler. Use the Try-it links to run each snippet in the browser. Remember: binding with .scroll(handler) is deprecated — these demos show legacy syntax you will encounter in older code.

📚 Binding & Triggering

Legacy .scroll() signatures for binding handlers on the window or overflow containers and firing events programmatically.

Example 1 — Bind Handler with .scroll(handler) on $(window)

The canonical legacy pattern — append to a log when the user scrolls the page.

jQuery
$( window ).scroll( function() {
  $( "#log" ).append( "Handler for scroll called. " );
} );
Try It Yourself

How It Works

$(window).scroll(fn) registers the function on the window object. jQuery internally routes this to .on("scroll", fn). The handler runs each time the page scroll position changes. The same pattern works on $("#panel").scroll(fn) for overflow containers.

Example 2 — Pass eventData with .scroll(eventData, handler)

Since jQuery 1.4.3, pass a threshold before the handler — it arrives as event.data.

jQuery
function check( threshold ) {
  var y = $( window ).scrollTop();
  $( "#status" ).text(
    y > threshold ? "Past " + threshold + "px — show back-to-top" : "Near top"
  );
}

$( window ).scroll( { threshold: 200 }, function( e ) {
  check( e.data.threshold );
} );
check( 200 );
Try It Yourself

How It Works

jQuery stores the { threshold: 200 } object and injects it into event.data when scroll fires. The check() helper reads scrollTop() to decide UI state. Modern equivalent: .on("scroll", { threshold: 200 }, fn).

Example 3 — Trigger Scroll with No-Argument .scroll()

Calling .scroll() without a handler fires the scroll event programmatically — bound handlers run once per call.

jQuery
var count = 0;

$( "#target" ).scroll( function() {
  count++;
  $( "#log" ).text(
    "Handler called " + count + " time(s). scrollTop: " + $( this ).scrollTop() + "px"
  );
} );

$( "#trigger" ).on( "click", function() {
  $( "#target" ).scroll();
} );
Try It Yourself

How It Works

The first .scroll(function(){ ... }) binds a handler on #target. The button calls $("#target").scroll() with no arguments — that synthetically fires scroll. Replace with $("#target").trigger("scroll") for clarity. This does not move scroll position — use .scrollTop() for that.

📈 Migration & Throttling

Compare legacy and modern APIs, and throttle expensive work inside .scroll(handler).

Example 4 — Migration: .scroll(fn) vs .on("scroll", fn)

Both bind the same scroll event on window — .on() is the recommended API for new code on jQuery 3.7.1.

jQuery
// Modern (recommended)
$( window ).on( "scroll", function() {
  $( "#log" ).append(
    "<div>.on('scroll') handler — scrollTop " + $( window ).scrollTop() + "px</div>"
  );
} );

// Legacy (deprecated): $( window ).scroll( function() { ... } );

$( "#go" ).on( "click", function() {
  $( window ).trigger( "scroll" );
} );
Try It Yourself

How It Works

Under the hood, .scroll(fn) calls .on("scroll", fn). Migration is a straight rename with no behavior change for simple window bindings. The button uses .trigger("scroll") — the modern replacement for no-arg .scroll().

Example 5 — Throttled Legacy .scroll(handler)

Never run heavy DOM work on every scroll event — throttle progress updates inside the handler.

jQuery
var raw = 0, throttled = 0, lastRun = 0, interval = 150;

$( window ).scroll( function() {
  raw++;
  $( "#raw" ).text( raw );
  var now = Date.now();
  if ( now - lastRun >= interval ) {
    lastRun = now;
    throttled++;
    var doc = $( document ).height() - $( window ).height();
    var pct = doc ? Math.round( $( window ).scrollTop() / doc * 100 ) : 0;
    $( "#throttled" ).text( throttled );
    $( "#bar" ).css( "width", pct + "%" ).text( pct + "%" );
  }
} );
Try It Yourself

How It Works

Every scroll event increments the raw counter immediately. The throttled block runs at most once every 150ms — so progress bar updates stay responsive without blocking the main thread on every wheel tick. Apply the same pattern when you migrate to .on("scroll", fn).

🚀 Common Use Cases

  • Reading legacy code — recognize $(window).scroll(fn) as equivalent to .on("scroll", fn) in older infinite-scroll scripts.
  • Page scroll indicators — legacy tutorials bind .scroll() on window to update progress bars and back-to-top buttons.
  • Overflow container scroll$("#chat").scroll(fn) reacts when a chat log or data table body scrolls.
  • Programmatic trigger$("#target").scroll() from a button — replace with .trigger("scroll").
  • Shared eventData$(window).scroll({ threshold: 300 }, fn) passes metadata without closures.
  • Maintaining legacy admin UIs — many jQuery 1.x panels still use .scroll() — know how to migrate safely to jQuery 3.x.

🧠 How .scroll() Routes Through jQuery

1

You call .scroll()

With a function argument, jQuery treats it as a bind request. With no arguments, it treats it as a trigger request. Bind on $(window) for page scroll or on overflow elements for container scroll.

dispatch
2

Bind path

.scroll(handler) delegates internally to .on("scroll", handler) — the handler is stored in jQuery’s event system on the matched element (window or overflow container).

.on("scroll")
3

Trigger path

No-arg .scroll() delegates to .trigger("scroll") — bound handlers run when scroll fires, without a real user scroll. Does not change scrollTop.

.trigger("scroll")
4

jQuery object returned

Both paths return the original collection for chaining — throttle inside the handler because scroll can fire dozens of times per second during wheel or touch gestures.

📝 Notes

  • Deprecated since jQuery 3.3 — do not use .scroll(handler) or .scroll(eventData, handler) in new code. Use .on("scroll") instead. Unlike .error(), .scroll() is not removed in jQuery 3.x.
  • Bind with .scroll(handler) since jQuery 1.0; eventData form since 1.4.3.
  • No-argument .scroll() triggers the event since jQuery 1.0 — prefer .trigger("scroll").
  • Bind on $(window) for page scroll or on overflow elements whose content exceeds their box.
  • .scrollTop() gets or sets position — it is not the same as the .scroll() event shorthand.
  • Never run heavy DOM work on every scroll event — throttle or debounce inside handlers.
  • Remove handlers with .off("scroll") — not by calling .scroll(undefined).
  • For the full modern scroll guide — throttling, progress bars, and .trigger("scroll") — see the jQuery scroll event tutorial.

Browser Support

The underlying scroll event fires on window and overflow elements when scroll position changes in browsers jQuery targets. The .scroll() method itself is a jQuery API — it works in jQuery 1.x, 2.x, and 3.x. Binding via .scroll(handler) is deprecated since 3.3 but still functional; triggering via no-arg .scroll() also remains supported.

jQuery 1.0+

jQuery .scroll() method

Supported across all jQuery versions you are likely to maintain. Deprecated binding since 3.3 — use .on('scroll') for new projects. Unlike .error() (removed in 3.0), .scroll() still works in jQuery 3.x. Native equivalent for binding: element.addEventListener('scroll', fn). Native equivalent for trigger: .trigger('scroll') or dispatchEvent.

100% With jQuery loaded
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
.scroll() Legacy API

Bottom line: Safe in legacy jQuery projects. Migrate bindings to .on('scroll') and triggers to .trigger('scroll') when updating scroll-driven UI. Always throttle expensive handlers.

Conclusion

The jQuery .scroll() method is the legacy shorthand for binding and triggering scroll handlers on the window or overflow elements. Use .scroll(handler) or .scroll(eventData, handler) to bind — both deprecated since jQuery 3.3. Use no-argument .scroll() to trigger — equivalent to .trigger("scroll"). Unlike .error(), it still works in jQuery 3.x. It is not the same as .scrollTop(), which reads or sets position.

For new code, prefer .on("scroll", fn) for binding and .trigger("scroll") for programmatic firing. Bind on the element that actually scrolls, throttle expensive work, and never confuse event binding with position APIs. When you encounter .scroll() in older infinite-scroll and sticky-header scripts, recognize it, understand it, and migrate when practical. For throttling, progress bars, and the complete modern scroll workflow, continue with the jQuery scroll event tutorial.

💡 Best Practices

✅ Do

  • Use .on("scroll", handler) for all new scroll bindings on window or overflow elements
  • Use .trigger("scroll") instead of no-arg .scroll()
  • Throttle or debounce expensive progress and layout code inside handlers
  • Use .scrollTop() to read or set position — pair with .on("scroll") to react
  • Read the modern scroll event tutorial for progress bars and lazy-load patterns

❌ Don’t

  • Write new scroll handlers with deprecated .scroll(handler)
  • Confuse .scroll(fn) (event bind) with .scrollTop() (position get/set)
  • Bind scroll on an element that does not actually overflow or scroll
  • Assume scroll fires a predictable number of times during a fast wheel gesture
  • Confuse .scroll(fn) (bind) with .scroll() (trigger)
  • Copy deprecated patterns from old tutorials without modernizing them

Key Takeaways

Knowledge Unlocked

Six things to remember about .scroll()

Legacy bind, modern migrate.

6
Core concepts
data 02

eventData

Since 1.4.3

Handler
() 03

.scroll()

Trigger

No args
.on 04

.on("scroll")

Modern

Replace
top 05

.scrollTop()

Position

Not event
3.3 06

Deprecated

Since 3.3

Not removed

❓ Frequently Asked Questions

The .scroll() method has two roles. With a handler argument — .scroll(handler) or .scroll(eventData, handler) — it binds a function that runs when the user scrolls a matched element. Bind on $(window) for page scroll or on overflow elements like $('#panel') for container scroll. With no arguments — .scroll() — it triggers the scroll event on each matched element, running bound handlers. Both forms have been part of jQuery since 1.0; the binding form is deprecated since 3.3.
Deprecated, not removed. The binding signatures .scroll(handler) and .scroll(eventData, handler) are deprecated since jQuery 3.3 — use .on('scroll', handler) instead. Unlike .error(), which was removed entirely in jQuery 3.0, .scroll() still works in jQuery 3.x for backward compatibility. The no-argument .scroll() trigger form also remains supported, though .trigger('scroll') is clearer.
.scroll(handler) registers a callback — it does not fire the event immediately. .scroll() with no arguments triggers the scroll event programmatically on every matched element, the same as .trigger('scroll'). The handler form is deprecated for binding; the no-arg form is a trigger shorthand. Bind on the element whose scrollTop or scrollLeft actually changes — $(window) for page scroll or a specific overflow container.
.scroll() is an event shorthand — it binds or triggers the scroll event. .scrollTop() is a separate method that gets or sets the vertical scroll position of an element (returns a number or sets pixels). Use .scroll(handler) or .on('scroll', handler) to react when scrolling happens; use .scrollTop() to read or change position. They are not interchangeable — binding .scroll() does not move the page, and .scrollTop(100) does not register an event listener.
Replace .scroll(fn) with .on('scroll', fn). Replace .scroll(data, fn) with .on('scroll', data, fn). Replace no-arg .scroll() with .trigger('scroll'). Replace .unbind('scroll') cleanup with .off('scroll'). Under the hood, .scroll(handler) already delegates to .on('scroll') — migration is a straight rename with no behavior change for simple window or overflow bindings.
Yes. Scroll can fire dozens of times per second during wheel, touch, or scrollbar drag — never run heavy DOM work on every raw event. Wrap progress bars, parallax checks, and sticky-nav logic in throttle (or debounce when you only need the final position) inside your handler, whether you use legacy .scroll(fn) or modern .on('scroll', fn). Example 5 on this page demonstrates throttling inside a legacy .scroll() handler.
Did you know?

jQuery event shorthands like .scroll(handler) were thin wrappers around .bind("scroll", handler) before .on() unified the API in jQuery 1.7. When you call .scroll(fn) today, jQuery still routes through the same event system as .on("scroll", fn) — which is why migration is a rename with no behavior change for simple window bindings. jQuery removed .error() in 3.0 but kept .scroll() as deprecated — a softer fate for scroll-driven UI still common in legacy infinite-scroll and admin panels. Do not confuse it with .scrollTop(), which predates the event shorthand and solves a completely different problem.

Next: jQuery Attributes

Get and set HTML attributes with .attr() — use .prop() for checked and selected state.

Attributes hub →

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.

6 people found this page helpful