Skip to content

Commit d695115

Browse files
authored
fix: safari (#209)
* update the docs * fix: safari * allow a few more bytes * allow even more bytes
1 parent bc68649 commit d695115

File tree

3 files changed

+37
-21
lines changed

3 files changed

+37
-21
lines changed

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@
8484
"bundlesize": [
8585
{
8686
"path": "./umd/scroll-into-view-if-needed.min.js",
87-
"maxSize": "1.5 kB"
87+
"maxSize": "1.75 kB"
8888
},
8989
{
9090
"path": "./umd/scroll-into-view-if-needed.js",
91-
"maxSize": "2.3 kB"
91+
"maxSize": "3 kB"
9292
}
9393
],
9494
"lint-staged": {

src/compute.ts

+19-16
Original file line numberDiff line numberDiff line change
@@ -226,12 +226,15 @@ export const compute = (
226226
}
227227

228228
// Workaround Chrome's behavior on clientHeight/clientWidth after introducing visualViewport
229+
// https://www.quirksmode.org/blog/archives/2016/02/chrome_change_b.html
229230
const viewportWidth = window.visualViewport
230231
? window.visualViewport.width
231232
: viewport.clientWidth
232233
const viewportHeight = window.visualViewport
233234
? window.visualViewport.height
234235
: viewport.clientHeight
236+
const viewportX = window.scrollX || window.pageXOffset
237+
const viewportY = window.scrollY || window.pageYOffset
235238

236239
// If the element is already visible we can end it here
237240
if (scrollMode === 'if-needed') {
@@ -284,7 +287,7 @@ export const compute = (
284287
targetBlock = targetRect.top
285288
}
286289
if (viewport === frame) {
287-
blockScroll = frame.scrollTop + targetBlock
290+
blockScroll = viewportY + targetBlock
288291
} else {
289292
// prevent scrollTop values that overflow the scrollHeight
290293
const offset = Math.min(
@@ -301,7 +304,7 @@ export const compute = (
301304
targetBlock = targetRect.top + targetRect.height / 2
302305
}
303306
if (viewport === frame) {
304-
blockScroll = frame.scrollTop + targetBlock - frame.clientHeight / 2
307+
blockScroll = viewportY + targetBlock - frame.clientHeight / 2
305308
} else {
306309
// prevent negative scrollTop values
307310
const offset =
@@ -323,7 +326,7 @@ export const compute = (
323326
targetBlock = targetRect.bottom
324327
}
325328
if (viewport === frame) {
326-
blockScroll = frame.scrollTop + targetBlock - frame.clientHeight
329+
blockScroll = viewportY + targetBlock - frame.clientHeight
327330
} else {
328331
// prevent negative scrollTop values
329332
const offset =
@@ -343,15 +346,15 @@ export const compute = (
343346

344347
if (viewport === frame) {
345348
const offset = alignNearest(
346-
frame.scrollTop,
347-
frame.scrollTop + viewportHeight,
349+
viewportY,
350+
viewportY + viewportHeight,
348351
viewportHeight,
349-
frame.scrollTop + targetBlock,
350-
frame.scrollTop + targetBlock + targetRect.height,
352+
viewportY + targetBlock,
353+
viewportY + targetBlock + targetRect.height,
351354
targetRect.height
352355
)
353356

354-
blockScroll = frame.scrollTop + offset
357+
blockScroll = viewportY + offset
355358
} else {
356359
const offset = alignNearest(
357360
frameRect.top,
@@ -373,7 +376,7 @@ export const compute = (
373376
targetInline = targetRect.left
374377
}
375378
if (viewport === frame) {
376-
inlineScroll = frame.scrollLeft + targetInline
379+
inlineScroll = viewportX + targetInline
377380
} else {
378381
// prevent scrollLeft values that overflow the scrollLeft
379382
const offset = Math.min(
@@ -391,7 +394,7 @@ export const compute = (
391394
targetInline = targetRect.left + targetRect.width / 2
392395
}
393396
if (viewport === frame) {
394-
inlineScroll = frame.scrollLeft + targetInline - frame.clientWidth / 2
397+
inlineScroll = viewportX + targetInline - frame.clientWidth / 2
395398
} else {
396399
// prevent negative scrollLeft values
397400
const offset =
@@ -413,7 +416,7 @@ export const compute = (
413416
targetInline = targetRect.right
414417
}
415418
if (viewport === frame) {
416-
inlineScroll = frame.scrollLeft + targetInline - frame.clientWidth
419+
inlineScroll = viewportX + targetInline - frame.clientWidth
417420
} else {
418421
// prevent negative scrollLeft values
419422
const offset =
@@ -433,15 +436,15 @@ export const compute = (
433436

434437
if (viewport === frame) {
435438
const offset = alignNearest(
436-
frame.scrollLeft,
437-
frame.scrollLeft + viewportWidth,
439+
viewportX,
440+
viewportX + viewportWidth,
438441
viewportWidth,
439-
frame.scrollLeft + targetInline,
440-
frame.scrollLeft + targetInline + targetRect.width,
442+
viewportX + targetInline,
443+
viewportX + targetInline + targetRect.width,
441444
targetRect.width
442445
)
443446

444-
inlineScroll = frame.scrollLeft + offset
447+
inlineScroll = viewportX + offset
445448
} else {
446449
const offset = alignNearest(
447450
frameRect.left,

src/index.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,20 @@ export interface Options {
88
inline?: ComputeOptions['inline']
99
}
1010

11+
// Wait with checking if native smooth-scrolling exists until scrolling is invoked
12+
// This is much more friendly to server side rendering envs, and testing envs like jest
13+
let supportsScrollBehavior
14+
1115
// Some people might use both "auto" and "ponyfill" modes in the same file, so we also provide a named export so
1216
// that imports in userland code (like if they use native smooth scrolling on some browsers, and the ponyfill for everything else)
1317
// the named export allows this `import {auto as autoScrollIntoView, ponyfill as smoothScrollIntoView} from ...`
1418
export default (target: Element, maybeOptions: Options | boolean = true) => {
1519
let options: Options = {}
1620

21+
if (supportsScrollBehavior === undefined) {
22+
supportsScrollBehavior = 'scrollBehavior' in document.documentElement.style
23+
}
24+
1725
// Handle alignToTop for legacy reasons
1826
if (maybeOptions === true || maybeOptions === null) {
1927
options = { block: 'start', inline: 'nearest' }
@@ -36,11 +44,16 @@ export default (target: Element, maybeOptions: Options | boolean = true) => {
3644

3745
instructions.forEach(({ el, top, left }) => {
3846
// browser implements the new Element.prototype.scroll API that supports `behavior`
39-
if (el.scroll) {
47+
// and guard window.scroll with supportsScrollBehavior
48+
if (el.scroll && supportsScrollBehavior) {
4049
el.scroll({ top, left, behavior })
4150
} else {
42-
el.scrollTop = top
43-
el.scrollLeft = left
51+
if (el === document.documentElement) {
52+
window.scrollTo(left, top)
53+
} else {
54+
el.scrollTop = top
55+
el.scrollLeft = left
56+
}
4457
}
4558
})
4659
}

0 commit comments

Comments
 (0)