jQuery Scrolling — Complete Guide to .scrollTop(), Scroll Events, and Animations
In this tutorial, you will learn about jquery scrolling. We cover key concepts, practical examples, and best practices to help you master this topic.
jQuery scrolling methods let you read and control scroll position, detect scroll events, animate smooth scrolling to elements, and build scroll-based UI behaviors like Infinite Scroll and sticky headers.
What You'll Learn
- Getting and setting scroll position with .scrollTop() and .scrollLeft()
- Scrolling to elements with .animate()
- Detecting scroll events and throttling
- Building infinite scroll and sticky navigation
- Smooth scroll implementations
Why It Matters
Scrolling is one of the most common user interactions. Controlling scroll position and responding to scroll events is essential for navigation, Lazy Loading, progress indicators, and scroll-triggered animations.
Real-World Use
A blog with infinite scroll that loads more posts when the user reaches the bottom, a sticky table of contents that highlights the current section on scroll, and a "Back to Top" button that animates smoothly up.
Scroll Flow
flowchart TD
A[User Scrolls] --> B[scroll Event]
B --> C[Throttle/Debounce]
C --> D[Check Position]
D --> E{Near Bottom?}
D --> F{Past Header?}
E -->|Yes| G[Load More Content]
F -->|Yes| H[Stick Header]
F -->|No| I[Unstick Header]
style B fill:#e6f3ff,stroke:#4a90d9,stroke-width:2px
Getting and Setting Scroll Position
// Get scroll position
var scrollTop = $(window).scrollTop();
var scrollLeft = $(window).scrollLeft();
console.log('Scroll position:', scrollTop, scrollLeft);
// Set scroll position
$(window).scrollTop(0); // Scroll to top
$(window).scrollLeft(200); // Scroll 200px from left
// Scroll a specific element (not window)
var $container = $('.scrollable-div');
var pos = $container.scrollTop();
$container.scrollTop(100);
Expected output: .scrollTop() returns the number of pixels the element is scrolled vertically. Setting it scrolls to that position immediately.
Smooth Scrolling to an Element
// Smooth scroll to an element
$('html, body').animate({
scrollTop: $('#section2').offset().top - 20 // 20px offset
}, 500);
// With easing
$('html, body').animate({
scrollTop: $('#target').offset().top
}, {
duration: 800,
easing: 'swing',
complete: function() {
console.log('Scroll complete');
}
});
// Click handler for anchor links
$('a[href^="#"]').on('click', function(e) {
e.preventDefault();
var target = $(this.getAttribute('href'));
if (target.length) {
$('html, body').animate({
scrollTop: target.offset().top - 50
}, 600);
}
});
Expected output: The page smoothly scrolls to the target element's position, stopping 50px above it for a fixed header.
Scroll Event Detection
$(window).on('scroll', function() {
var scrollPos = $(window).scrollTop();
console.log('Scrolled:', scrollPos);
});
Throttling Scroll Events
Scroll events fire rapidly. Always throttle or debounce:
// Throttle: fire at most once per 200ms
var lastScrollTime = 0;
$(window).on('scroll', function() {
var now = Date.now();
if (now - lastScrollTime < 200) return;
lastScrollTime = now;
// Your scroll logic here
var scrollPos = $(window).scrollTop();
updateUI(scrollPos);
});
// Or use a debounce timer
var scrollTimer;
$(window).on('scroll', function() {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function() {
// Fires 100ms after scrolling stops
var pos = $(window).scrollTop();
console.log('Scroll stopped at:', pos);
}, 100);
});
Sticky Header on Scroll
var header = $('.site-header');
var stickyClass = 'sticky';
var headerOffset = header.offset().top;
$(window).on('scroll', function() {
var scrollPos = $(window).scrollTop();
if (scrollPos >= headerOffset) {
header.addClass(stickyClass);
} else {
header.removeClass(stickyClass);
}
});
// CSS:
// .site-header.sticky {
// position: fixed;
// top: 0;
// left: 0;
// right: 0;
// z-index: 1000;
// box-shadow: 0 2px 4px rgba(0,0,0,0.1);
// }
Back to Top Button
var $backToTop = $('<button class="back-to-top">Top</button>')
.appendTo('body')
.hide();
$(window).on('scroll', function() {
if ($(window).scrollTop() > 300) {
$backToTop.fadeIn();
} else {
$backToTop.fadeOut();
}
});
$backToTop.on('click', function() {
$('html, body').animate({ scrollTop: 0 }, 400);
});
Expected output: The button fades in after scrolling 300px down. Clicking it animates smoothly back to the top.
Infinite Scroll
var page = 1;
var loading = false;
$(window).on('scroll', function() {
if (loading) return;
var scrollTop = $(window).scrollTop();
var windowHeight = $(window).height();
var docHeight = $(document).height();
// Trigger when within 200px of the bottom
if (scrollTop + windowHeight >= docHeight - 200) {
loading = true;
$('#loading-spinner').show();
page++;
$.get('/api/items?page=' + page, function(data) {
if (data.items.length > 0) {
data.items.forEach(function(item) {
$('.items-list').append(
$('<div class="item">').text(item.name)
);
});
loading = false;
$('#loading-spinner').hide();
} else {
// No more items
$('#loading-spinner').text('No more items');
}
});
}
});
Scroll Progress Indicator
$(window).on('scroll', function() {
var scrollTop = $(window).scrollTop();
var docHeight = $(document).height() - $(window).height();
var scrollPercent = (scrollTop / docHeight) * 100;
$('.progress-bar').width(scrollPercent + '%');
});
// CSS:
// .progress-bar {
// position: fixed;
// top: 0;
// left: 0;
// height: 3px;
// background: #3498db;
// transition: width 0.1s;
// }
Scrollable Container
// Create a custom scrollable div
var $container = $('<div class="scroll-container">')
.css({
width: '400px',
height: '300px',
overflow: 'auto'
})
.appendTo('body');
$container.on('scroll', function() {
var $this = $(this);
var scrollTop = $this.scrollTop();
var scrollHeight = this.scrollHeight;
var clientHeight = this.clientHeight;
if (scrollTop + clientHeight >= scrollHeight - 50) {
console.log('Reached bottom of container');
}
});
Common Mistakes
Not throttling scroll events - Scroll fires hundreds of times per second. Without throttling, your handlers cause jank and poor performance.
Using $(window).scrollTop() on non-window elements - For scrollable divs, use
$('.container').scrollTop(), not$(window).scrollTop().Forgetting animation queue on scroll - Calling .animate() inside a scroll handler without .stop() causes queued animations to accumulate. Stop the previous animation first.
Not accounting for fixed headers in scroll-to - When scrolling to an element, subtract the fixed header height:
target.offset().top - headerHeight.Infinite scroll without loading guard - Without a
loadingflag, scroll triggers at the bottom fire multiple API calls. Always guard against concurrent loads.
Practice Questions
- How do you get the current vertical scroll position?
- How do you smoothly scroll to a specific element on the page?
- Why is throttling important for scroll events?
- How do you detect when the user has scrolled to the bottom of the page?
- How do you scroll a specific div (not the window)?
Challenge: Build a one-page marketing site with smooth scroll navigation, a sticky header, a scroll progress bar, a "Back to Top" button, and active section highlighting in the navigation as the user scrolls.
FAQ
Mini Project
Build a scroll-driven story page with sections that fade in and animate when they scroll into view (scroll-triggered animations). Include a scroll-based progress bar, smooth navigation between sections, and a floating table of contents that highlights the active section.
What's Next
Scroll interactions respond to jQuery events. Learn more about binding and managing events in jQuery.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro