Skip to content

Commit

Permalink
fix(overlay): block scroll strategy throwing off scroll behavior feat…
Browse files Browse the repository at this point in the history
…ure detection

To avoid a scrolling animation when we disable scrollig, we remove and re-set the `scroll-behavior` property on the body without feature checking it. The problem is that since we've set the property to *something*, our `scrollBehaviorSupported` feature check will be thrown off because it checks for `'scrollBehavior' in document.documentElement.style`.

Fixes angular#17221.
  • Loading branch information
crisbeto committed Mar 3, 2020
1 parent 9343d08 commit 5f3ecde
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 14 deletions.
29 changes: 16 additions & 13 deletions src/cdk/overlay/scroll/block-scroll-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,16 @@
import {ScrollStrategy} from './scroll-strategy';
import {ViewportRuler} from '@angular/cdk/scrolling';
import {coerceCssPixelValue} from '@angular/cdk/coercion';
import {supportsScrollBehavior} from '@angular/cdk/platform';

/**
* Extended `CSSStyleDeclaration` that includes `scrollBehavior` which isn't part of the
* built-in TS typings. Once it is, this declaration can be removed safely.
* @docs-private
*/
type ScrollBehaviorCSSStyleDeclaration = CSSStyleDeclaration & {scrollBehavior: string};
const scrollBehaviorSupported = supportsScrollBehavior();

/**
* Strategy that will prevent the user from scrolling while the overlay is visible.
*/
export class BlockScrollStrategy implements ScrollStrategy {
private _previousHTMLStyles = {top: '', left: ''};
private _previousScrollPosition: { top: number, left: number };
private _previousScrollPosition: {top: number, left: number};
private _isEnabled = false;
private _document: Document;

Expand All @@ -31,7 +27,7 @@ export class BlockScrollStrategy implements ScrollStrategy {
}

/** Attaches this scroll strategy to an overlay. */
attach() { }
attach() {}

/** Blocks page-level scroll while the attached overlay is open. */
enable() {
Expand All @@ -58,8 +54,8 @@ export class BlockScrollStrategy implements ScrollStrategy {
if (this._isEnabled) {
const html = this._document.documentElement!;
const body = this._document.body!;
const htmlStyle = html.style as ScrollBehaviorCSSStyleDeclaration;
const bodyStyle = body.style as ScrollBehaviorCSSStyleDeclaration;
const htmlStyle = html.style;
const bodyStyle = body.style;
const previousHtmlScrollBehavior = htmlStyle.scrollBehavior || '';
const previousBodyScrollBehavior = bodyStyle.scrollBehavior || '';

Expand All @@ -71,12 +67,19 @@ export class BlockScrollStrategy implements ScrollStrategy {

// Disable user-defined smooth scrolling temporarily while we restore the scroll position.
// See https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-behavior
htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = 'auto';
// Note that we don't mutate the property if the browser doesn't support `scroll-behavior`,
// because it can throw off feature detections in `supportsScrollBehavior` which
// checks for `'scrollBehavior' in documentElement.style`.
if (scrollBehaviorSupported) {
htmlStyle.scrollBehavior = bodyStyle.scrollBehavior = 'auto';
}

window.scroll(this._previousScrollPosition.left, this._previousScrollPosition.top);

htmlStyle.scrollBehavior = previousHtmlScrollBehavior;
bodyStyle.scrollBehavior = previousBodyScrollBehavior;
if (scrollBehaviorSupported) {
htmlStyle.scrollBehavior = previousHtmlScrollBehavior;
bodyStyle.scrollBehavior = previousBodyScrollBehavior;
}
}
}

Expand Down
11 changes: 10 additions & 1 deletion src/cdk/platform/features/scrolling.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,18 @@ export const enum RtlScrollAxisType {
/** Cached result of the way the browser handles the horizontal scroll axis in RTL mode. */
let rtlScrollAxisType: RtlScrollAxisType|undefined;


/** Cached result of whether the browser supports `scrollBehavior`. */
let scrollBehaviorSupported: boolean;

/** Check whether the browser supports scroll behaviors. */
export function supportsScrollBehavior(): boolean {
return !!(typeof document == 'object' && 'scrollBehavior' in document.documentElement!.style);
if (scrollBehaviorSupported == null) {
scrollBehaviorSupported =
!!(typeof document == 'object' && 'scrollBehavior' in document.documentElement!.style);
}

return scrollBehaviorSupported;
}

/**
Expand Down

0 comments on commit 5f3ecde

Please sign in to comment.