Implementing Automatic Scroll to Top on Route Changes in Angular

Nov 22, 2025 · Programming · 6 views · 7.8

Keywords: Angular Routing | Scroll Position Restoration | Single Page Application

Abstract: This article provides a comprehensive analysis of handling page scroll position during route transitions in Angular applications. For Angular 6.1 and later, it details the built-in scrollPositionRestoration configuration option for effortless scroll position management. For earlier versions, it presents custom solutions using Router and Location services, implementing scroll stack management through navigation event monitoring to maintain correct scroll positions during forward and backward navigation. The article compares different approaches and includes complete code examples with implementation details.

Problem Background and Challenges

In single-page application (SPA) development, page scroll behavior during route transitions is a common user experience concern. When users scroll to the bottom of a long page and click a link to navigate to a new page, if the new page has limited content, users might mistakenly believe content is missing because the browser maintains the previous scroll position, displaying the bottom area of the new page instead of the top.

This issue is particularly noticeable in content-intensive applications such as news websites, e-commerce platforms, or documentation systems, where users expect to start browsing from the top after each page transition.

Built-in Solution for Angular 6.1+

Angular version 6.1 introduced native scroll position restoration functionality, which can be enabled through simple router configuration. This is currently the recommended approach as it's officially supported by the framework, well-maintained, and performance-optimized.

In the application's main routing module, simply add the scrollPositionRestoration: 'enabled' option to the RouterModule.forRoot() method:

import { RouterModule } from '@angular/router';

const routes = [
  // Route definitions...
];

@NgModule({
  imports: [RouterModule.forRoot(routes, {
    scrollPositionRestoration: 'enabled'
  })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

This configuration ensures:

According to the Angular official blog, this feature is expected to become default behavior in future major releases, but currently (as of Angular 13) it still requires explicit enablement.

Custom Implementation for Angular 6.0 and Earlier

For older versions without built-in support, manual scroll position management is necessary. A common simple approach involves listening for route end events and scrolling to top:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
  constructor(private router: Router) { }

  ngOnInit() {
    this.router.events.subscribe((event) => {
      if (event instanceof NavigationEnd) {
        window.scrollTo(0, 0);
      }
    });
  }
}

However, this simple method has significant drawbacks: it breaks normal browser forward/backward behavior. When users click the back button, the page should return to its previous scroll position, but this implementation forces scrolling to top.

Complete Scroll Position Management Solution

To address forward/backward navigation issues, more sophisticated scroll position management is required. The following implementation uses scroll position stacking to differentiate between navigation types:

import { Component, OnInit } from '@angular/core';
import { Router, NavigationStart, NavigationEnd } from '@angular/router';
import { Location, PopStateEvent } from "@angular/common";

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent implements OnInit {
  private lastPoppedUrl: string;
  private yScrollStack: number[] = [];

  constructor(private router: Router, private location: Location) { }

  ngOnInit() {
    // Listen for browser history changes (forward/backward)
    this.location.subscribe((ev: PopStateEvent) => {
      this.lastPoppedUrl = ev.url;
    });

    // Listen for router events
    this.router.events.subscribe((event: any) => {
      if (event instanceof NavigationStart) {
        // For new navigation (not forward/backward), save current scroll position
        if (event.url != this.lastPoppedUrl) {
          this.yScrollStack.push(window.scrollY);
        }
      } else if (event instanceof NavigationEnd) {
        if (event.url == this.lastPoppedUrl) {
          // Forward/backward navigation: restore previous scroll position
          this.lastPoppedUrl = undefined;
          const scrollY = this.yScrollStack.pop();
          window.scrollTo(0, scrollY || 0);
        } else {
          // New page navigation: scroll to top
          window.scrollTo(0, 0);
        }
      }
    });
  }
}

Core logic of this implementation:

Special Considerations for Server-Side Rendering (SSR)

In server-side rendering environments, scroll position management may face additional challenges. As mentioned in the reference article, the built-in scrollPositionRestoration option might not work properly in SSR mode under certain circumstances.

Recommended solutions for SSR applications:

  1. First ensure using the latest Angular version, as SSR support continues to improve
  2. If built-in functionality fails, fall back to custom implementation
  3. Handle initial scrolling in the ngAfterViewInit lifecycle hook to ensure DOM is fully rendered

Performance Optimization and Best Practices

When implementing scroll position management, consider the following performance aspects:

Summary and Recommendations

For handling scroll position restoration in Angular applications, recommended priority order:

  1. Preferred Approach: For Angular 6.1+, use built-in scrollPositionRestoration: 'enabled'
  2. Compatibility Approach: For older versions or special requirements, adopt complete custom scroll management implementation
  3. Testing Validation: Test scroll behavior across various navigation scenarios (link clicks, browser forward/backward, programmatic navigation)

As the Angular framework continues to evolve, scroll position management is expected to become simpler and more reliable. Developers should monitor official documentation and version updates to adopt optimal solutions promptly.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.