Unnötige Farben vermeiden

Paul Lewis

Einführung

Das Zeichnen der Elemente für eine Website oder Anwendung kann sehr teuer werden und sich negativ auf die Laufzeitleistung auswirken. In diesem Artikel sehen wir uns kurz an, was das Painting im Browser auslösen kann und wie Sie unnötige Farbverläufe verhindern können.

Malen: Schneller Überblick

Eine der Hauptaufgaben eines Browsers besteht darin, Ihr DOM und CSS in Pixel auf dem Bildschirm umzuwandeln. Dazu wird ein ziemlich komplexer Prozess verwendet. Zuerst wird das Markup gelesen und daraus wird ein DOM-Baum erstellt. Ähnlich verhält es sich mit dem CSS, aus dem das CSSOM erstellt wird. Anschließend werden DOM und CSSOM kombiniert. So erreichen wir schließlich eine Struktur, von der aus wir mit der Darstellung einiger Pixel beginnen können.

Der Malprozess selbst ist interessant. In Chrome wird dieser kombinierte DOM- und CSS-Baum von einer Software namens Skia gerastert. Wenn Sie schon einmal mit dem canvas-Element gearbeitet haben, wird Ihnen die Skia-API sehr vertraut vorkommen. Es gibt viele moveTo- und lineTo-Funktionen sowie eine Reihe erweiterter Funktionen. Im Grunde werden alle Elemente, die gerendert werden müssen, in eine Sammlung von Skia-Aufrufen zusammengefasst, die ausgeführt werden können. Die Ausgabe besteht aus einer Reihe von Bitmaps. Diese Bitmaps werden auf die GPU hochgeladen, die sie dann zusammensetzt, um das endgültige Bild auf dem Bildschirm zu erzeugen.

Dom zu Pixeln

Wichtig ist, dass sich die Arbeitslast von Skia direkt auf die Stile auswirkt, die Sie auf Ihre Elemente anwenden. Wenn Sie algorithmisch anspruchsvolle Stile verwenden, muss Skia mehr Arbeit leisten. Colt McAnlis hat einen Artikel darüber geschrieben, wie sich CSS auf das Rendergewicht von Seiten auswirkt. Lesen Sie ihn, um mehr zu erfahren.

Trotzdem braucht es Zeit für den Farbauftrag. Wenn wir den Wert nicht reduzieren, überschreiten wir unser Frame-Budget von ca. 16 ms. Die Nutzer werden bemerken, dass wir Frames übersehen haben und dies als Verzögerung empfinden, was letztlich die Nutzererfahrung unserer App beeinträchtigt. Wir möchten wirklich nicht, dass dies erforderlich ist. Schauen wir uns also an, welche Aspekte dazu führen, dass Farbanstriche erforderlich sind und was wir dagegen tun können.

Scrollen

Wenn Sie im Browser nach oben oder unten scrollen, müssen die Inhalte neu gerendert werden, bevor sie auf dem Bildschirm angezeigt werden. Im Idealfall ist das nur ein kleiner Bereich. Aber selbst dann können auf die zu zeichnenden Elemente komplexe Stile angewendet werden. Nur weil Sie eine kleine Fläche streichen müssen, bedeutet das nicht, dass es schnell geht.

Mit der Funktion „Farbrechtecke anzeigen“ in den Chrome-Entwicklertools können Sie sehen, welche Bereiche neu gezeichnet werden. Klicken Sie dazu einfach auf das kleine Zahnrad in der rechten unteren Ecke. Wenn Sie die Entwicklertools geöffnet haben, interagieren Sie einfach mit der Seite. Sie sehen dann blinkende Rechtecke, die anzeigen, wo und wann Chrome einen Teil Ihrer Seite gerendert hat.

Rechtecke für Malen in den Chrome-Entwicklertools anzeigen
Farbrechtecke in den Chrome-Entwicklertools anzeigen

Die Scrollleistung ist entscheidend für den Erfolg Ihrer Website. Nutzer bemerken es sofort, wenn das Scrollen auf Ihrer Website oder in Ihrer App nicht flüssig funktioniert, und das gefällt ihnen nicht. Daher ist es für uns wichtig, die Bildaktualisierung beim Scrollen möglichst gering zu halten, damit Nutzer keine Ruckler sehen.

Ich habe bereits einen Artikel zur Scrollleistung geschrieben. Sehen Sie sich diesen an, wenn Sie mehr über die Details der Scrollleistung erfahren möchten.

Interaktionen

Interaktionen sind eine weitere Ursache für Malarbeiten: Hovering, Klicks, Berührungen, Ziehen. Jedes Mal, wenn der Nutzer eine dieser Interaktionen ausführt, z. B. den Mauszeiger bewegt, muss Chrome das betroffene Element neu zeichnen. Ähnlich wie beim Scrollen sinkt die Framerate, wenn eine große und komplexe Darstellung erforderlich ist.

Jeder wünscht sich schöne, flüssige Interaktionsanimationen. Auch hier müssen wir überprüfen, ob die Stile, die sich in unserer Animation ändern, zu viel Zeit kosten.

Eine unglückliche Kombination

Eine Demo mit teuren Farben
Eine Demo mit teuren Farben

Was passiert, wenn ich scrolle und die Maus gleichzeitig bewege? Es ist durchaus möglich, dass ich unbeabsichtigt mit einem Element „interagiere“, während ich daran vorbeiscrolle, und so eine teure Farbgebung auslöse. Das könnte wiederum mein Frame-Budget von etwa 16,7 ms überschreiten (die Zeit, die wir unterschreiten müssen, um 60 Frames pro Sekunde zu erreichen). Ich habe eine Demo erstellt, um Ihnen zu zeigen, was ich meine. Wenn Sie scrollen und die Maus bewegen, sollten die Hover-Effekte sichtbar werden. Sehen wir uns an, was die Chrome-Entwicklertools dazu sagen:

Teure Frames in den Chrome-Entwicklertools
In den Chrome-Entwicklertools werden teure Frames angezeigt

Im Bild oben sehen Sie, dass die DevTools die Malaktion registrieren, wenn ich den Mauszeiger auf einen der Blöcke bewege. Ich habe in meiner Demo einige sehr schwere Stile verwendet, um den Punkt zu verdeutlichen. Daher stoße ich an mein Frame-Budget und überschreite es gelegentlich. Ich möchte diese Malarbeiten auf keinen Fall unnötigerweise machen, vor allem nicht beim Scrollen, wenn noch andere Arbeit ansteht.

Wie können wir das verhindern? Die Lösung ist ziemlich einfach umzusetzen. Der Trick besteht darin, einen scroll-Handler anzuhängen, der die Hover-Effekte deaktiviert und einen Timer für die Reaktivierung einrichtet. Das bedeutet, dass beim Scrollen keine teuren Interaktions-Paints ausgeführt werden müssen. Wenn Sie lange genug angehalten haben, können Sie sie wieder einschalten.

Hier ist der Code:

// Used to track the enabling of hover effects
var enableTimer = 0;

/*
 * Listen for a scroll and use that to remove
 * the possibility of hover effects
 */
window.addEventListener('scroll', function() {
  clearTimeout(enableTimer);
  removeHoverClass();

  // enable after 1 second, choose your own value here!
  enableTimer = setTimeout(addHoverClass, 1000);
}, false);

/**
 * Removes the hover class from the body. Hover styles
 * are reliant on this class being present
 */
function removeHoverClass() {
  document.body.classList.remove('hover');
}

/**
 * Adds the hover class to the body. Hover styles
 * are reliant on this class being present
 */
function addHoverClass() {
  document.body.classList.add('hover');
}

Wie Sie sehen können, verwenden wir eine -Klasse für den Body, um nachzuverfolgen, ob Mouseover-Effekte zugelassen sind oder nicht. Für die zugrunde liegenden Stile ist es erforderlich, dass diese Klasse vorhanden ist:

/* Expect the hover class to be on the body
 before doing any hover effects */
.hover .block:hover {
 
}

So einfach ist das.

Fazit

Die Renderingleistung ist entscheidend für die Nutzerfreundlichkeit Ihrer Anwendung. Sie sollten immer darauf achten, dass die Arbeitslast für das Malen unter 16 ms liegt. Dazu sollten Sie die Entwicklertools während des gesamten Entwicklungsprozesses verwenden, um Engpässe zu identifizieren und zu beheben, sobald sie auftreten.

Unbeabsichtigte Interaktionen, insbesondere bei Elementen mit vielen Farben, können sehr kostspielig sein und beeinträchtigen die Rendering-Leistung. Wie Sie gesehen haben, können wir das mit einem kleinen Code-Snippet beheben.

Sehen Sie sich Ihre Websites und Anwendungen an. Könnten sie einen kleinen Schutzanstrich vertragen?