Skip to content

Commit aa259ab

Browse files
authored
fix(mobile safari): scrollingElement is a false positive (#257)
* Fix mobile safari * revert to lazy init * verified iPhone X works using my own device * disable iPhone X tests for now
1 parent cab6f4c commit aa259ab

File tree

5 files changed

+25
-17
lines changed

5 files changed

+25
-17
lines changed

src/compute.ts

+4-5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ declare global {
2222
}
2323

2424
import { CustomScrollAction, Options } from './types'
25+
import getViewport from './viewport'
2526

2627
// @TODO better shadowdom test, 11 = document fragment
2728
const isElement = el =>
@@ -49,6 +50,7 @@ const canOverflow = (
4950
}
5051

5152
const isScrollable = (el, skipOverflowHiddenElements: boolean) =>
53+
el === getViewport() ||
5254
(hasScrollableSpace(el, 'Y') &&
5355
canOverflow(el, 'Y', skipOverflowHiddenElements)) ||
5456
(hasScrollableSpace(el, 'X') &&
@@ -218,7 +220,6 @@ export default (
218220
}
219221

220222
const targetRect = target.getBoundingClientRect()
221-
const viewport = document.scrollingElement || document.documentElement
222223

223224
// Collect all the scrolling boxes, as defined in the spec: https://drafts.csswg.org/cssom-view/#scrolling-box
224225
const frames: Element[] = []
@@ -228,10 +229,7 @@ export default (
228229
isElement((parent = target.parentNode || target.host)) &&
229230
checkBoundary(target)
230231
) {
231-
if (
232-
isScrollable(parent, skipOverflowHiddenElements) ||
233-
parent === viewport
234-
) {
232+
if (isScrollable(parent, skipOverflowHiddenElements)) {
235233
frames.push(parent)
236234
}
237235

@@ -241,6 +239,7 @@ export default (
241239

242240
// Workaround Chrome's behavior on clientHeight/clientWidth after introducing visualViewport
243241
// https://www.quirksmode.org/blog/archives/2016/02/chrome_change_b.html
242+
const viewport = getViewport()
244243
const viewportWidth = window.visualViewport
245244
? window.visualViewport.width
246245
: Math.min(viewport.clientWidth, window.innerWidth)

src/index.ts

+4-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
Options as BaseOptions,
66
ScrollBehavior,
77
} from './types'
8+
import getViewport from './viewport'
89

910
export interface StandardBehaviorOptions extends BaseOptions {
1011
behavior?: ScrollBehavior
@@ -19,8 +20,6 @@ export interface Options<T = any> extends BaseOptions {
1920

2021
// Wait with checking if native smooth-scrolling exists until scrolling is invoked
2122
// This is much more friendly to server side rendering envs, and testing envs like jest
22-
let supportsScrollBehavior
23-
let scrollingElement
2423

2524
// tslint:disable-next-line: ban-types
2625
const isFunction = (arg: any): arg is Function => {
@@ -34,21 +33,15 @@ const defaultBehavior = (
3433
actions: CustomScrollAction[],
3534
behavior: ScrollBehavior = 'auto'
3635
) => {
37-
// Because of quirksmode
38-
if (!scrollingElement) {
39-
scrollingElement = document.scrollingElement || document.documentElement
40-
}
41-
if (supportsScrollBehavior === undefined) {
42-
supportsScrollBehavior = 'scrollBehavior' in scrollingElement.style
43-
}
44-
36+
const viewport = getViewport()
37+
const supportsScrollBehavior = 'scrollBehavior' in viewport.style
4538
actions.forEach(({ el, top, left }) => {
4639
// browser implements the new Element.prototype.scroll API that supports `behavior`
4740
// and guard window.scroll with supportsScrollBehavior
4841
if (el.scroll && supportsScrollBehavior) {
4942
el.scroll({ top, left, behavior })
5043
} else {
51-
if (el === scrollingElement) {
44+
if (el === viewport) {
5245
window.scrollTo(left, top)
5346
} else {
5447
el.scrollTop = top

src/viewport.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// memoize for perf
2+
let viewport
3+
4+
// return the current viewport depending on wether quirks mode is active or not
5+
export default () => {
6+
if (!viewport) {
7+
viewport =
8+
document.compatMode === 'CSS1Compat'
9+
? document.documentElement
10+
: document.scrollingElement || document.documentElement
11+
}
12+
13+
return viewport as HTMLElement
14+
}

tests/web-platform/browserstack.conf.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ exports.config = {
1919
{ browser: 'firefox' },
2020
{ browser: 'IE', browser_version: '11.0' },
2121
{ browser: 'Edge' },
22-
{ os_version: '11.0', device: 'iPhone X', real_mobile: 'true' },
22+
// @TODO investigate how to make iPhone X able to run the tests
23+
//{ os_version: '11.0', device: 'iPhone X', real_mobile: 'true' },
2324
{ os_version: '8.0', device: 'Google Pixel', real_mobile: 'true' },
2425
{ os_version: '7.0', device: 'Samsung Galaxy S8', real_mobile: 'true' },
2526
],

tests/web-platform/css/cssom-view/scrollintoview.html

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<!DOCTYPE html>
22
<title>CSSOM View - scrollIntoView</title>
33
<meta charset="utf-8">
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
45
<link rel="author" title="Chris Wu" href="mailto:pwx.frontend@gmail.com">
56
<link rel="help" href="https://drafts.csswg.org/cssom-view/#dom-element-scrollintoview">
67
<link rel="help" href="https://heycam.github.io/webidl/#es-operations">

0 commit comments

Comments
 (0)