Is it possible to test for scrollIntoView browser compatibility?
Asked Answered
B

5

11

I am looking for a way to do a real-time test for scrollIntoView functionality of my user's browser. This is not a "caniuse" check; rather I want to have graceful degradation. I am using jQuery, and would like to use a preventDefault() if scrollIntoView is functional.

I started with:

        if (window.scrollIntoView) {
            e.preventDefault();
            $('p#result').text('scrollIntoView is available');
        } else {
            $('#result').text('scrollIntoView is not available');
        }

but I see that window.scrollIntoView is undefined in the inspector. However, because scrollIntoView works (in my version of Chrome and FireFox), it shouldn't be undefined. What other options can I have to see if it the user's browser supports the function?

Blubber answered 24/10, 2017 at 20:40 Comment(1)
developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView window does not have this methodGavrilla
S
7

That method is on elements, so you can check document.documentElement.scrollIntoView.

Snowonthemountain answered 24/10, 2017 at 20:42 Comment(1)
Works like a charm. I used document.body.scrollIntoView and the code executed correctly. Thank you!Blubber
C
27

It could also be handy to check if scrollIntoView only support boolean true / false or also supports behaviour for smooth scrolling.

var isSmoothScrollSupported = 'scrollBehavior' in document.documentElement.style;
if(isSmoothScrollSupported) {
    element.scrollIntoView({behavior: "smooth", block: "end", inline: "nearest"});    
} else {
    element.scrollIntoView(false);
}
Caprifoliaceous answered 27/6, 2018 at 19:34 Comment(3)
Isn't it the opposite? i.e. passing an object to scrollIntoView() only when isSmoothScrollSupported is true?Chock
@Benjamin Update my answer. Thanks for your commentCaprifoliaceous
Nice check. In Safari scrollIntoViewOptions are allowed, but it does not support scrollBehavior, so the above check will fail and will fallback to the alternative behaviour, which is worse for the user. That's why we preferred the other solution with try/catch now: https://mcmap.net/q/955937/-is-it-possible-to-test-for-scrollintoview-browser-compatibilityProconsul
V
11

I found that at least for the WaterFox browser (and likely a few more), scrollBehavior did exist in document.documentElement.style as Stefan van de Vooren suggests, yet the browser would throw the following error:

TypeError: 'block' member of ScrollIntoViewOptions 'center' is not a valid 
value for enumeration ScrollLogicalPosition.

A simple try-catch statement solved the issue for us:

try {
   element.scrollIntoView({
     behavior: "smooth",
     block: "center"
   });
} catch (error) {
   //fallback to prevent browser crashing
   element.scrollIntoView(false);
}
Vaporizer answered 18/9, 2018 at 20:9 Comment(0)
S
7

That method is on elements, so you can check document.documentElement.scrollIntoView.

Snowonthemountain answered 24/10, 2017 at 20:42 Comment(1)
Works like a charm. I used document.body.scrollIntoView and the code executed correctly. Thank you!Blubber
M
0

You could check it like this:


if (typeof document.body.scrollIntoView === 'function') {
  // Do smth.
  yourNode.scrollIntoView();
}
Mayotte answered 18/11, 2019 at 13:42 Comment(0)
C
0

I was not able to easily validate with unit tests these kind of checks, without having to implement odd overriding mechanisms exposing the unit test side to logic that it should not really know about.

Based on the answer of @DrewJex I ended in writing something entirely based on the how the browser behaves, which is way much easier to test as well.

const scrollIntoView = (element, params = true) => {
  try {
    element.scrollIntoView(params);
    return true;
  } catch (e) {
    return false;
  }
};

const scrollTo = (element, params = {}) => {
  try {
    window.scrollTo({ ...params, top: element.offsetTop });
    return true;
  } catch (e) {
    return false;
  }
};

export const scrollToElement = (element) =>
  scrollIntoView(element, { behavior: 'smooth' }) ||
  scrollIntoView(element) ||
  scrollTo(element, { behavior: 'smooth' }) ||
  scrollTo(element);
Connaught answered 20/12, 2021 at 10:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.