navigationdom-eventsonbluronfocusvisibilitychange

Document visibilitychange versus window blur/focus, what is the difference, when to use which?


In ECMAscript (=Javascript) there are two ways to check if the user is away from your page or not. You can either listen for a "visibilitychange" event on the document or you can listen for "blur" and "focus" events on the window. Is there a difference between them?


Solution

  • Yes. There are two significant differences. The first difference between them can be seen on phones. Unlike desktop and tablet devices, phone navigation will usually let you change the browser tab in TWO steps.

    On desktops and most tablets however, you just click/touch which tab you want to go to and you are there. Looks like this:

    tablet

    As for phone navigation, in most cases, there are TWO steps. You first start like this:

    phone

    and when you touch the TABS icon you see a fly-over menu like this:

    phone tabs

    This is where the main difference between visibilitychange and blur/focus becomes obvious and can also be important. According to "visibilitychange" the user is not yet away from your page at this stage. But according to "blur/focus" the user is away.

    The second difference is that a parent window and an iframe inside it cannot share focus i.e. they cannot have focus at the same time even though they can be hidden or visible at the same time via visibilitychange. This can be especially important if you are reading keyboard events.

    View this example to see the difference in action.

    We have also used the following code to put them in a race and see which one fires earlier. The results were simply inconsistent. Sometimes visibilitychange fired before blur or focus and other times vice versa. There were even times when it fired between a focus and a blur.

    document.addEventListener("visibilitychange", visChngF);
    function visChngF(){
              if (document.hidden) { 
                    console.log("hidden means user is gone");
              } else {
                    console.log("visible means user is back");
              }
    }
        
    window.addEventListener('blur', blurHappenedF);
    function blurHappenedF(){
              console.log("blur means user is away");
    }
        
    window.addEventListener('focus', focusHappenedF);
    function focusHappenedF(){
              console.log("focus means user is here");
    }
    

    Last but not least: There are no built-in booleans like "isBlurred" or "isFocused" within window. But there is hasFocus() method which can be used to find which document has focus. View it on MDN. Remember that if you are using blur/focus it is always a good idea to check where the focus is when load event from window fires, that is because a first-landing and a page-refresh may yield different results for the initial focus.