IntersectionObserver API erratic in Safari

Viewed 1631

I have an IntersectionObserver API which checks the visibility of the blocks to change the header and menu items classes, it Works perfectly in Chrome, but it is very erratic in Safari (v. 13.0.5). I also inserted the polyfill, but doesn't help. This is the code I use

/* Intersection observer */
let sections = document.querySelectorAll(".homesection");

let options = {
    root: null,
    rootMargin: '100px 0px 0px 0px',
    threshold: 0.7
};

let observer = new IntersectionObserver(function(entries,observer){
    entries.forEach(entry => {
        let thisID = entry.target.getAttribute('id');
        $('nav .top-menu li a.selected').removeClass("selected");
        $('body.loaded nav .top-menu li a[href=#'+thisID+']').addClass("selected");

        if ( $("body").hasClass("loaded") ) {
            if ( thisID == "home" || thisID == "top" ) {
                $('body').removeClass("scrolled");
                $("body").addClass("topscroll");
            } else {
                $('body').addClass("scrolled");
                $("body").removeClass("topscroll");
            }           
        }


    });
}, options);

sections.forEach(section => {
    observer.observe(section);
});

The issue is mostly visible when loading the page the first time, it doesn't trigger the script and is very erratic on observing the elements, but on second load or click to some internal js action it works more-less fine. Any idea what could be the problem?

2 Answers

Found a workaround to wrap the initial loading setup (adding classes, hashname initialisation etc.) in a setTimeout with a few hundred millisecond delay, seems to work nicely now also with Safari.

The problem could be related to browser's quirks mode, as explained in the relative GitHub issue.

What happens, in Safari, is that in quirks mode document.body.clientHeight returns the viewport height. In no quirks mode, it returns the element height.

If the problem is the quirk mode you can fix it adding the doctype at the beginning of your served HTML:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset=UTF-8>
    <title>Hello World!</title>
  </head>
  <body>
  </body>
</html>
Related