@isa/utils/scroll-position
Utility library providing scroll position restoration and scroll-to-top functionality for Angular applications.
Overview
The @isa/utils/scroll-position library enables automatic scroll position preservation across route navigations and provides a reusable scroll-to-top button component. It stores scroll positions in session storage and restores them when users navigate back to previously visited routes, creating a smoother user experience for applications with long, scrollable content.
Key Features:
- Automatic Scroll Restoration: Preserve and restore scroll position across route navigation
- Session Storage Integration: Persists scroll positions in session storage for reliability
- Route-Level Control: Enable/disable restoration per route via route data configuration
- Scroll-to-Top Button: Ready-to-use component with accessibility support
- Configurable Delays: Control timing of scroll restoration with optional delays
Type: Utility library with functions, providers, and components
Installation
import {
provideScrollPositionRestoration,
injectRestoreScrollPosition,
storeScrollPosition,
ScrollTopButtonComponent
} from '@isa/utils/scroll-position';
API Reference
Providers
provideScrollPositionRestoration()
Provides an environment initializer that automatically stores scroll positions during navigation and page unload events.
Returns: EnvironmentProviders
Behavior:
- Listens to
NavigationStartevents from the Angular Router - Listens to the
beforeunloadwindow event - Only stores scroll position for routes with
scrollPositionRestoration: truein their route data - Stores positions in session storage using the current URL as the key
Usage:
// In app.config.ts
import { provideScrollPositionRestoration } from '@isa/utils/scroll-position';
export const appConfig: ApplicationConfig = {
providers: [
provideScrollPositionRestoration(),
// other providers...
]
};
Functions
storeScrollPosition()
Stores the current viewport scroll position in session storage using the current router URL as the key.
Returns: Promise<void>
Usage:
import { Component } from '@angular/core';
import { storeScrollPosition } from '@isa/utils/scroll-position';
@Component({
selector: 'app-product-list',
// ...
})
export class ProductListComponent {
async onNavigateAway() {
// Manually store scroll position before navigating
await storeScrollPosition();
// navigation logic...
}
}
injectRestoreScrollPosition()
Returns a function that restores the scroll position from session storage for the current route.
Returns: (delay?: number) => Promise<void> - An async function that accepts an optional delay parameter
Parameters (returned function):
delay?: number- Optional delay in milliseconds before restoring scroll position (default: 0)
Behavior:
- Retrieves stored scroll position using the current router URL as the key
- Waits for the specified delay to ensure the DOM is ready
- Clears the stored position after restoration
- Does nothing if no position was stored for the current URL
Usage:
import { Component, OnInit } from '@angular/core';
import { injectRestoreScrollPosition } from '@isa/utils/scroll-position';
@Component({
selector: 'app-product-list',
// ...
})
export class ProductListComponent implements OnInit {
private restoreScrollPosition = injectRestoreScrollPosition();
async ngOnInit() {
// Restore scroll position after 100ms to ensure content is rendered
await this.restoreScrollPosition(100);
}
}
Components
ScrollTopButtonComponent
A standalone component that displays a button to scroll back to the top of the page or a specific scrollable element.
Selector: utils-scroll-top-button
Inputs:
target: Window | HTMLElement- The scroll target (default:window)
Features:
- Automatically shows/hides based on scroll position (shows when scrolled down)
- Respects user's
prefers-reduced-motionsetting - Uses smooth scrolling when motion is not reduced
- Includes proper accessibility attributes (
aria-label) - E2E testing ready with
data-whatattribute
Styling:
- Host class:
utils-scroll-top-button - Uses
ViewEncapsulation.Nonefor flexible styling - Button uses tertiary color and large size from
@isa/ui/buttons
Usage:
// Basic usage (scrolls window)
import { ScrollTopButtonComponent } from '@isa/utils/scroll-position';
@Component({
selector: 'app-product-list',
imports: [ScrollTopButtonComponent],
template: `
<div class="content">
<!-- Your scrollable content -->
</div>
<utils-scroll-top-button />
`
})
export class ProductListComponent {}
// Custom scroll target (specific element)
@Component({
selector: 'app-modal',
imports: [ScrollTopButtonComponent],
template: `
<div #scrollContainer class="modal-content">
<!-- Long content -->
</div>
<utils-scroll-top-button [target]="scrollContainer" />
`
})
export class ModalComponent {
@ViewChild('scrollContainer') scrollContainer!: ElementRef<HTMLElement>;
}
Styling Example:
// Custom positioning and appearance
utils-scroll-top-button {
position: fixed;
bottom: 2rem;
right: 2rem;
z-index: 1000;
}
Usage Examples
Complete Setup with Automatic Restoration
// 1. Configure in app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideScrollPositionRestoration } from '@isa/utils/scroll-position';
export const appConfig: ApplicationConfig = {
providers: [
provideScrollPositionRestoration(),
]
};
// 2. Enable in route configuration
export const routes: Routes = [
{
path: 'products',
component: ProductListComponent,
data: { scrollPositionRestoration: true }
}
];
// 3. Restore position in component
import { Component, OnInit } from '@angular/core';
import { injectRestoreScrollPosition, ScrollTopButtonComponent } from '@isa/utils/scroll-position';
@Component({
selector: 'app-product-list',
imports: [ScrollTopButtonComponent],
template: `
<div class="product-grid">
@for (product of products(); track product.id) {
<app-product-card [product]="product" />
}
</div>
<utils-scroll-top-button />
`
})
export class ProductListComponent implements OnInit {
private restoreScrollPosition = injectRestoreScrollPosition();
async ngOnInit() {
await this.loadProducts();
// Restore scroll after content loads
await this.restoreScrollPosition(100);
}
}
Manual Control for Custom Scenarios
import { Component } from '@angular/core';
import { storeScrollPosition, injectRestoreScrollPosition } from '@isa/utils/scroll-position';
@Component({
selector: 'app-custom-navigation',
// ...
})
export class CustomNavigationComponent {
private restoreScrollPosition = injectRestoreScrollPosition();
async onCustomNavigateAway() {
// Store before custom navigation logic
await storeScrollPosition();
this.customNavigationService.navigate();
}
async onCustomNavigateBack() {
// Restore after returning
await this.restoreScrollPosition(200);
}
}
Route Configuration
To enable automatic scroll restoration on specific routes, add the scrollPositionRestoration property in route data:
export const routes: Routes = [
{
path: 'example',
component: ExampleComponent,
data: {
scrollPositionRestoration: true
}
}
];
Dependencies
@angular/common- ViewportScroller for scroll operations@angular/core- Core Angular functionality (inject, signals, etc.)@angular/router- Router integration for navigation events@isa/core/storage- Session storage provider for persistence@isa/ui/buttons- Icon button component for ScrollTopButtonComponent@isa/icons- Icon assets (isaSortByUpMedium)@ng-icons/core- Icon system integration
Notes
- Scroll positions are stored in session storage and cleared after restoration
- The automatic restoration only applies to routes with
scrollPositionRestoration: truein their data - The scroll-to-top button respects accessibility preferences (
prefers-reduced-motion) - Manual restoration includes a configurable delay to ensure DOM readiness before scrolling
- The scroll-to-top button automatically shows/hides based on scroll position