I posted this in the issue thread, but I'll post it again here.
My team has been using what the angular team uses on this repo on angular.io. Just make a service and inject it like usual. Then, on ngAfterViewInit on each page you want this behavior, just call this.[scroll service variable name].scrollToTop(). Finally, you'll need to add this to the top of <body> in index.html: <div id="top-of-page"></div>
Service Code:
import { Injectable, Inject } from '@angular/core'; import { PlatformLocation } from '@angular/common'; import { DOCUMENT } from '@angular/platform-browser'; import {fromEvent} from 'rxjs/observable/fromEvent'; export const topMargin = 16; /** * A service that scrolls document elements into view */ @Injectable() export class ScrollService { private _topOffset: number | null; private _topOfPageElement: Element; // Offset from the top of the document to bottom of any static elements // at the top (e.g. toolbar) + some margin get topOffset() { if (!this._topOffset) { const toolbar = this.document.querySelector('md-toolbar.app-toolbar'); this._topOffset = (toolbar && toolbar.clientHeight || 0) + topMargin; } return this._topOffset; } get topOfPageElement() { if (!this._topOfPageElement) { this._topOfPageElement = this.document.getElementById('top-of-page') || this.document.body; } return this._topOfPageElement; } constructor( @Inject(DOCUMENT) private document: any, private location: PlatformLocation) { // On resize, the toolbar might change height, so "invalidate" the top offset. fromEvent(window, 'resize').subscribe(() => this._topOffset = null); } /** * Scroll to the element with id extracted from the current location hash fragment. * Scroll to top if no hash. * Don't scroll if hash not found. */ scroll() { const hash = this.getCurrentHash(); const element: HTMLElement = hash ? this.document.getElementById(hash) : this.topOfPageElement; this.scrollToElement(element); } /** * Scroll to the element. * Don't scroll if no element. */ scrollToElement(element: Element) { if (element) { element.scrollIntoView(); if (window && window.scrollBy) { // Scroll as much as necessary to align the top of `element` at `topOffset`. // (Usually, `.top` will be 0, except for cases where the element cannot be scrolled all the // way to the top, because the viewport is larger than the height of the content after the // element.) window.scrollBy(0, element.getBoundingClientRect().top - this.topOffset); // If we are very close to the top (<20px), then scroll all the way up. // (This can happen if `element` is at the top of the page, but has a small top-margin.) if (window.pageYOffset < 20) { window.scrollBy(0, -window.pageYOffset); } } } } /** Scroll to the top of the document. */ scrollToTop() { this.scrollToElement(this.topOfPageElement); } /** * Return the hash fragment from the `PlatformLocation`, minus the leading `#`. */ private getCurrentHash() { return this.location.hash.replace(/^#/, ''); } }