Gunnar Bittersmann: Strange Rendering-Bug im Firefox

Beitrag lesen

problematische Seite

@@Gunnar Bittersmann

Fixe Hintergründe mit Transparenz – die Grafikkarte will ja was zu tun haben. Oder läuft das gar über die CPU? Dem Lüfter soll’s egal sein, für wen er rotieren muss. Die angesprochene JavaScript-Lösung könnte performanter sein.

Gesagt, getan.

Um auf dynamische Änderungen zu reagieren, ist wohl JavaScript das bessere Mittel der Wahl. Irgendwelche clevere CSS-Verrenkungen mögen zwar funktionieren, aber wenn man nach 3 Tagen selbst nicht mehr weiß, warum sie das tun, sind sie doch nicht so clever.

Also einen IntersectionObserver genommen und damit eine Klasse "scrolled" am body- oder html-Element gesetzt bzw. gelöscht. (Mit JavaScript wird nicht direkt an CSS-Eigenschaften rumgefummelt!)

Zunächst hatte ich die Tabellenüberschrift unter Beobachtung: 👀

const intersectionObserver = new IntersectionObserver(
  entries => {
    document.body.classList.toggle('scrolled', entries[0].intersectionRatio == 0);
  },
  { rootMargin: `-${document.querySelector('header').offsetHeight + 36}px` }
);

intersectionObserver.observe(document.querySelector('caption'));

Besonders unschön daran ist, dass damit nicht auf mögliche spätere Änderungen der Höhe des Headers reagiert wird.

Besser wäre es, ein Element im Auge zu haben, das sich ganz am Anfang der Seite befindet und mitscrollt. Der header und seine Nachfahren scheiden wegen position: sticky aus.

Ich war schon drauf und dran, ein leeres div vor den header zu setzen …

Moment! Da ist ja schon ein Element ganz am Anfang der Seite: head!!! (Drei Ausrufezeichen. Nein, ich bin nicht verrückt.) Um den im Auge zu haben muss man ihn nur sichtbar machen:

head { display: block }

head > * { display: none }

und dann kann man ihn auch observieren: 👀

const intersectionObserver = new IntersectionObserver(
  entries => {
    document.body.classList.toggle('scrolled', entries[0].intersectionRatio == 0);
  },
  { rootMargin: '36px' }
);

intersectionObserver.observe(document.head);

Und wo ich gerade an Observern dran war, hab ich die Überwachung der Höhe des Headers auch auf ResizeObserver umgestellt. Ich nehme stark an, dass die Browser das mindestens ebenso performant – vermutlich sogar besser – implementiert haben als wenn man selbst Debouncing oder Throttling implementieren würde.

Vorher:

const debouncingDelay = 250;
const headerElement = document.querySelector('header');
let timeout;

const refreshHeaderHeight = () => {
  document.documentElement.style.setProperty(
    '--header-height', `${headerElement.offsetHeight}px`
  );
};

window.addEventListener('resize', () => {
  clearTimeout(timeout);
  timeout = setTimeout(refreshHeaderHeight, debouncingDelay);
});

refreshHeaderHeight();

Nachher:

const resizeObserver = new ResizeObserver(entries => {
  document.documentElement.style.setProperty(
    '--header-height', `${entries[0].target.offsetHeight}px`
  );
});

resizeObserver.observe(document.querySelector('header'));

Amazing discovery. Zu sehen bspw. bei Discovery (pun intended).

🖖 Живи довго і процвітай

--
When the power of love overcomes the love of power the world will know peace.
— Jimi Hendrix