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?

Sablefoste
  • 4,032
  • 3
  • 37
  • 58
  • https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView `window` does not have this method – Huangism Oct 24 '17 at 20:50

5 Answers5

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);
}
Stefan van de Vooren
  • 2,524
  • 22
  • 19
  • 4
    Isn't it the opposite? i.e. passing an object to `scrollIntoView()` only when `isSmoothScrollSupported` is `true`? – BenMorel Sep 06 '18 at 11:33
  • 2
    @Benjamin Update my answer. Thanks for your comment – Stefan van de Vooren Sep 09 '18 at 19:07
  • 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://stackoverflow.com/a/52393930/2590616 – RiZKiT Nov 06 '19 at 09:54
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);
}
Drew Jex
  • 845
  • 2
  • 13
  • 24
7

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

llama
  • 2,535
  • 12
  • 11
0

You could check it like this:


if (typeof document.body.scrollIntoView === 'function') {
  // Do smth.
  yourNode.scrollIntoView();
}
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);
Luca Borrione
  • 16,324
  • 8
  • 52
  • 66