Advertisement
  1. Photo & Video
  2. JavaScript
Photography

Wer braucht schon AMP? Lazy Load von responsive Bildern einfach gemacht mit Layzr.js

by
Difficulty:IntermediateLength:LongLanguages:

German (Deutsch) translation by Andreas Geibert (you can also view the original English article)

Googles "Accelerated Mobile Pages" (AMP) Project hat zuletzt geholfen, Webseites schneller zu machen. Mit ausgefeilten Techniken und einem starken Content Distribution Network (CDN) hat Google Webseiten, die AMP optimiert sind, unmittelbar schneller gemacht. AMP funktioniert dazu auch noch indirekt, hat es uns doch dazu bewegt, einmal hinter die Kulissen zu schauen, um die Optimierungen und Best-Practices von AMP zu erforschen. Auch wenn Du nicht vorhast, Deine Webseite für AMP zu optimieren, ist es nützlich, dass, dass Du die Todo-Liste um eine Seite für AMP zu optimieren kennst.

Einer dieser Optimierungspunkte ist eine Technik, die sich "Lazy Loading", also "spätes Laden" nennt, welche wir schon aus unserem letzten Artikel using AMP's custom element kennen. Über diese Technik werden zuerst nur die Bilder geladen, die der Benutzer unmittelbar über seinen Browser sehen kann. Die restlichen Bilder werden erst geladen, wenn der Benutzer scrollt und diese Bilder sichtbar werden müssen.

Lazy Loading erlaubt es einem Benutzer den Seiteninhalt schneller angezeigt zu bekommen. Außerdem can die dadurch entstandene, höhere Seitenladegeschwindigkeit Dein Suchmaschinenranking verbessern. Je mehr Bilder Du also auf einer Seite hast, desto mehr Geschwindigkeit kannst Du über Lazy Loading auf dieser Seite heraus holen.

In diesem Tutorials werden wir uns ansehen, wie Du Lazy Loading auf nicht AMP Seiten implementieren kannst und nutzen dazu ein Skript namens Layzr.js. Wir werden die <amp-img> Funktionalität von AMP so perfekt wie möglich nachbauen, werden aber zusätzlich noch ein paar spezielle Features von Layzr nutzen.

Lasst uns loslegen!

1. Basis Setup

Wie im Artikel "AMP Project: Will it Make Your Sites Faster?" habe ich ein Basis Layout mit fünf Bildern erstellt. Damit wir die Geschwindigkeit und Ladezeiten zwischen dem AMP und unserem Lazy Load Setup vergleichen können, erstellen wir also genau das gleiche fünf Bilder Layout. Ich zeige Dir später noch, wie Du dafür verschiedene Ladezeiten-Tests laufen lassen kannst.

In den Beispieldateien zu diesem Artikel findest Du sowohl die AMP Version, als auch die komplette, fertige Version dieses Tutorials. Ich habe beide Versionen hinzugefügt, damit Du Dich entscheiden kannst, welcher Ansatz für Dich besser passt.

Um dieses Tutorial am besten verfolgen zu können, solltest Du die Chrome Developer Tools verwenden (F12), den Netzwerk Tab darin öffnen, Den Cache deaktivieren und die Drosselung /Throttling) auf Regular 3G stellen  Damit simulieren wir eine durchschnittliche mobile Verbindung, welche Dir dann im Diagramm das Laden von Bildern in Echtzeit anzeigt und Dir damit hilft, ein besseres Verständnis dafür aufzubauen, wie Lazy Loading funktioniert.

Um die Seite mit verschiedenen Optionen neu zu laden, klicke mit der rechten Maustaste auf den Neu-Laden Button oder halte die linke Maustaste lange gedrückt. Danach bekommst Du ein Drop-Down angezeigt. Wähle "Empty Cache and Hard Reload" um zu simulieren, dass ein Benutzer Deine Seite zum ersten Mal lädt.

Emty cache and hard reload in Chrome Developer Tools

Die HTML Datei erstellen

Lass uns mit den Basics beginnen. Erstelle zuerst einen Projektordner und darin dann eine Datei namens index.html.

Öffne diese Datei zum Bearbeiten und füge folgenden Code hinzu:

Mit diesem Code erstellen wir erst einmal das HTML Grundgerüst und fügen etwas CSS hinzu, um sicher zu gehen, dass das body Element und die Bilder auf unserer Seite keine ungewollten Abstände haben.

Zusätzlich ergänzen wir noch margin: 0 auto; so dass die Bilder später zentriert erscheinen.

Layzr laden

Das layzr.js Skript hat zwei praktische CDN Quellen, die Du zum Laden verwenden kannst – wir entscheiden und für Cloudflare.

Füge noch folgenden Code vor dem schließenden </body> Tag ein.

Falls Du Layzr nicht von einem CDN laden willst, kannst Du das Skript auch einfach lokal herunter laden. Siehe dazu: https://github.com/callmecavs/layzr.js#download

Layzr instantiieren

Jetzt wo wir Layzr geladen haben, müssen wir dafür sorgen, dass es auch ausgeführt wird, wenn die Seite geladen wird. Um das zu erreichen, füge folgenden Code nach den script Tags, die Du vorher erstellt hast, ein:

Dieser Code erstellt zuerst eine Instanz, die Layzr enthält. Dann, wenn das DOM der Seite komplett geladen ist, wird diese Instanz verwendet, um Layzr zu starten.

Der gesamte Code sollte bis hierhin so aussehen:

2. Bilder hinzufügen (Normale Auflösung)

Layzr ist geladen und wir sind bereit dazu loszulegen und einige Bilder hinzuzufügen, um Layzr in Aktion zu sehen. Du kannst jegliche Bilder verwenden, die Du möchtest. Solltest Du aber genau die Bilder und Code-Beispiele aus diesem Tutorial verwenden wollen, kannst Du die Beispiel-Dateien zu diesem Tutorial herunter laden. Darin findest Du einen images Ordner mit Bildern, den Du in Dein eigenes Projekt kopieren kannst.

Damit Layzr diese Bilder korrekt verarbeitet, verwendest Du ein standard img Tag. Statt des standard scr Attributs, verwendest Du aber das data-normal Attribut, wie hier zu sehen:

Sicher gehen, dass Bilder eine Höhe haben

Für jedes Lay Loading Skript ist es wichtig, die genaue Höhe eines jeden Bildes zu kennen, um entscheiden zu können, welches es gerade nachladen muss, und welches noch nicht, weil es noch nicht im Sichtbarkeitsbereich des Browsers/Benutzers liegt.

Das Schwierige daran ist, dass ein Bild-Element noch keine Höhe hat, solange es nicht vollständig vom Browser geladen wurde. Das bedeutet, dass wir Breite und Höhe eines Bildes schon an das Lazy Load Skript übergeben müssen, bevor das jeweilige Bild geladen wurde.

Wir sehen und dazu zwei Methoden an. Eine für feste Größen, eine für responsive Bilder. Festen Bildern eine Höhe geben ist sehr einfach. Wie immer verwenden wir dazu einfach die standard Attribute height und width.

Versuche es einmal selbst und für img Elemente über dem Layzr script Tag ein und verwende die data-normal, height und width Attribute für jedes Bild, das Du über Lazy Load geladen haben möchtest..

Über feste Größen funktioniert Lazy Load schon einmal prima. Aber das hält die Bilder davon ab, responsive zu reagieren. Und das ist nicht optimal. Wir werden uns später noch ansehen, wie wir Bildern zwar eine Höhe, aber zusätzlich noch das responsive Verhalten geben können.

3. Einen Ladebereich festlegen

Standardmäßig zeigt Layzr nur die Bilder, die beim Laden einer Webseite im Sichtbereich des Browsers liegen. Für den Benutzer ist es aber meist besser, wenn Bilder, die kurz außerhalb seines sichtbaren Browserbereichs liegen, ebenfalls gleich mitgeladen werden, da er dann beim herunter Scrollen nicht auf das Laden der "neuen" Bilder warten muss.

Dies erreichst Du, wenn Du die Option threshold beim Instanziieren des Skripts übergibst. Die funktioniert so, dass Du einen Prozentsatz übergibst, der einen Teil des sichtbaren Browserbereichs beschreibt. Übergibst Du beispielsweise 100%, repräsentiert dies 100% der Browserfenster-Höhe, z.B. 1200px. In diesem Fall werden alle Bilder, die sich bis zu 1200px außerhalb des Browserfensters befinden ebenfalls gleich mit geladen.

Hie rein Beispiel – Hast Du z.B. zwei große Bilder, eines davon liegt etwas außerhalb des sichtbaren Bereichs, und "threshold" wurde auf 100 gesetzt, würden beide Bilder geladen werden:

Um die Option "threshold" zu setzen, ersetze folgende Zeilen im Code:

... mit diesem Code:

Du kannst den Wert so anpassen, dass er am betsen auf Deinen Anwendungsfall passt. Interessant an dieser Stelle ist vielleicht, dass AMPs Lazy Loading einen "threshold" Wert von ungefähr 200 nutzt.

4. Retina/HiDPI Bilder hinzufügen

Ein tolles Feature von Layzr ist, dass man Bilder für hochauflösende Geräte ganz einfach hinzufügen kann. Alles was Du machen musst, ist das Attribut data-retina hinzu zu fügen. Ein Beispiel:

Ändere alle Bildern in Deiner HTML Datei so, dass Sie Retina unterstützen:

5. Responsive Image Platzhalter und Unterbinden von Neuaufbau im Browser

Bilder, die über Lazy Loading geladen werden responsive zu machen, kann manchmal schwierig sein. Wie bereits erwähnt, muss Layzr wissen, wie hoch Bilder sind, um festzulegen, wann diese geladen werden müssen. Weil responsive Bilder Ihre Größe ständig ändern können, ist deren wahre Größe nicht vorhersehbar.

Zusätzlich müchten wir das Neu-Rendern von Inhalt (Reflow), und damit eventuelle Sprünge des Contents, verhindern. Reflow entsteht dadurch, dass ein Bild zuerst keine Höhe hat und nach dem fertigen Laden auf einmal seine wahre Höhe auf der Seite einnimmt, was meist bedeutet, dass der Inhalt um das Bild herum springt. Das kann Besucher Deiner Webseite ziemlich frustrieren, da sie versuchen, den Seiteninhalt zu lesen, welcher dann aber immer wieder durch nach und nach geladene Bilder hin und her springt.

Wir können beide Probleme beheben, in dem wir responsive Platzhalter für jedes Bild auf der Seite einsetzen. Die Platzhalter sorgen dann dafür, dass der Inhalt nicht neu positioniert werden muss, wenn Bilder geladen worden sind, und zusätzlich hat Layzr gleich die benötigten Höhenangaben der Bilder. Die Basis dafür bietet eine geniale Technik, die in diesem "A List Apart" Artikel mit dem Titel "Creating Intrinsic Ratios for Video" von Thierry Koblentz beschrieben wird.

Das einzig Wichtige ist, dass Du das Seitenverhältnis eines jeden Bildes kennst, weil Du dann über dieses Verhältnis das jeweilige Bild mit Hilfe von CSS in seiner Größe anpassen wirst.

Einen Seitenverhältnis Wrapper erstellen

Zuerst fügen wir um unser erstes Bild ein umschließendes div (Wrapper) hinzu – Dieses div wird unser Platzhalter. Das div selbst ändern wir dann in seiner Größe automatisch über CSS. Das darin befindliche Bild füllt das div dann komplett aus.

Das div bekommt noch eine CSS Klasse mit einer aussagekräftigen Bezeichnung, die sein Seitenverhältnis beschreibt. In unserem ersten Beispiel ist das Bild 960 Pixel breit und 640 Pixel hoch. Nun müssen wir heraus finden, welches Seitenverhältnis dies bedeutet.

640 (unsere Höhe) sind zwei Drittel von 960 (unsere Breite), was bedeutet, dass das Bild für jede zwei Einheiten Höhe, 3 Einheiten Breit ist. Seitenverhältnisse werden normalerweise als width:height (also breite:höhe), wie in dem bekannten 16:9 Format, angegeben. Das Verhältnis in unserem ersten Beispiel ist somit 3:2.

Um unser Seitenverhältnis (ratio) als aussagekräftige CSS Klasse, die unser Wrapper div erhält, zu definieren, wählen wir die Bezeichnung ratio_3_2.

Styling für Standard Seitenverhältnisse

Jetzt fügen wir das CSS hinzu, um die Funktionalität herzustellen.

Füge dazu folgenden Code zwischen die <style></style> Tags im head Bereich Deiner index.html Datei hinzu:

Dieser Selektor greift bei allen ratio_3_2 CSS Klassen, funktioniert aber ebenso bei allen anderen, die mit ratio_ beginnen. Das bedeutet, dass wir auch später noch so viele CSS Klassen für beliebig viele Seitenverhältnisse wie wir benötigen, hinzu fügen können.

In dieser Stylesheet Definition sorgen wir dafür, dass unser Wrapper immer 100% seiner, durch sein Elternelement vorgegebenen, verfügbaren Breite einnimmt. Wir setzen es auch noch auf position: relative; da wir das darin befindliche Bild gleich noch absolut positionieren werden, was wir uns später noch ansehen.

Dem Wrapper eine Höhe geben

Jetzt werden wir für unsere ratio_3_2 CSS Klasse, und nur für diese, folgenden Code hinzufügen:

Das padding-top sorgt dafür, dass das Seitenverhältnis in unserem div immer stimmt. Wie breit auch immer das div sein mag – dieses Padding hält die Höhe immer genau auf 66.666667%, was zwei Drittel der Breite sind und ein Seitenverhältnis von 3:2 darstellt.

Um heraus zu finden, welche Prozentzahl Du hier eintragen musst, finde einfach heraus, welchen prozentualen Wert Deine Höhe im Verhältnis zur Breite einnimmt. Das erreichst Du durch folgende Rechnung:

100% * (Höhe / Breite)

Für unser Verhältnis von 3:2 bedeutet dies z.B.: 100% * (2 / 3) = 66.666667%

Du kannst die korrekten Prozentzahlen für Deine benötigten Seitenverhältnisse selbst ausrechnen und bereits vordefiniert in Dein CSS schreiben, oder, wie im nachfolgenden Beispiel gezeigt, die CSS Funktion calc() verwenden:

padding-top: calc( 100% * (2 / 3) );

Das Bild ausgefüllt im Wrapper positionieren.

Egal wie breit das Browserfenster nun ist und wie viel Platz unser Seitenverhältnis Wrapper einnimmt, es behält immer exakt unsere festgelegten Dimensionen. Nun müssen wir also nur noch dafür sorgen, dass unser Bild das Wrapper div komplett ausfüllt und somit automatisch das richtige Verhältnis einimmt.

Wir erreichen dies, indem wir jedes Bild, das sich in einem Wrapper mit der Klasse ratio_ befindet, absolut positionieren, links oben ausrichten und es dann auf 100% Breite und Höhe bringen:

Schau Dir das Ergebnis einmal an und Du solltest sehen, dass das Bild jetzt seinen verfügbaren Platz komplett einnimmt und sich bei einer Veränderung der Browserbreite immer im richtigen Verhältnis anpasst.

Zusätzliche Seitenverhältnisse

Wahrscheinlich wirst Du Bilder in unterschiedlichsten Seitenverhältnissen haben und diese alle abdecken wollen. In diesem Beispiel arbeiten wir mit drei Bildern mit einem Verhältnis von 3:2 und dem vierten und fünften mit 16:9.

Um dieses Verhältnis ebenfalls abzudecken, führen wir eine neue CSS Klasse mit dem Namen ratio_16_9 und dem korrespondierenden padding-top Wert ein:

Füge die restlichen div Wrapper für Seitenverhätnisse um alle verbleibenden Bilder hinzu, indem Du die passenden CSS Klassen, basierend auf deren Seitenverhältnisse vergibst. Jetzt kannst Du auch alle height und width Attribute entfernen, da diese sowieso vom CSS überschrieben werden.

Lade nun einmal Deinen Browser neu und verändere die Browserbreite. Du wirst nun sehen, dass alle Bilder responsive sind und kein Springen des Inhalts durch neues Rendern geschieht.

6. srcset hinzufügen

Layzr unterstützt auch das srcset Attribut. Browser, die das srcset Attribut unterstützen, werden dieses bevorzugt gegenüber den Attributen data-normal und data-retina verwenden.

Aber anstatt nur das einfache srcset Attribut zu verwenden, sollte diese noch mit data- vorangestellt werden. Ganz wie bei den Anderen Attributen, die wir bisher verwendet haben.

Ändere den Code für Dein erstes Bild wie folgt:

Um zu sehen, was genau passiert, ziehe Deinen Browser so klein wie möglich, am besten auf 320px Breite. Danach lädst Du die Seite neu und siehst Dir an, was im Network Tab geschieht. Du solltest sehen, dass zuerst die kleinste Version des Bildes geladen wird. Nun ziehe den Browser langsam breiter und Du solltest sehen, dass dabei bald auch die mittleren und großen Versionen geladen werden.

Der Bilderordner aus dem Beispielprojekt enthält die einzelnen Beispielbilder in den Größen klein, mittel und groß. Füge nun das data-srcset Attribut in allen Bilder hinzu:

Eine Lade-Animation hinzufügen

Wir haben es schon fast geschafft. Aber für den letzten Schliff, fügen wir noch eine Lade-Animation hinzu. Das zeigt dem Benutzer an, welche Teile des Layouts noch als Platzhalter fungieren und welche Bilder im Begriff sind gerade zu laden.

Wir nutzen einen reinen CSS Preloader, welcher eine leicht modifizierte Version des Pens von Alan Shortis: https://codepen.io/alanshortis/pen/eJLVXr ist.

Um zu vermeiden, dass wir noch zusätzliche HTML Elemente einführen müssten, nutzen wir das :after Pseudo-Element, welches wir für jeden Wrapper für Seitenverhältnisse definieren. Füge folgendes CSS hinzu:

Dieser Code erzeugt ein kleines, kreisförmiges Lade-Icon, zentriert dieses und lässt es sich um 360 Grad in 0.75 Sekunden drehen.

Wir geben unseren Wrappern zusätzlich noch einen dunklen Hintergrund, um diese auf den ersten Blick von den restlichen Elementen auf der Seite abzuheben. Füge die Zeile background-color: #333; hinzu:

Zum Schluß müssen wir noch sicher stellen, dass die Lade-Animation unsere Bilder nicht überlagert. Um dies zu erreichen, geben wir unseren Bildern einen z-index: 1;, um sie eine Ebene über den Lade-Animationen zu positionieren.

Lade Deine Seite neu und nun solltest Du die Lade-Animationen in Aktion sehen können.

Der vollständige Code

Dein kompletter Code sollte nun folgendermaßen aussehen:

Zusammenfassung

Du hast nun ein Lazy-Loading System, das dem von AMP sehr nahe kommt, implementiert.

Es gibt einige Dinge, die AMP zwar automatisch übernimmt, z.B. kümmert es sich ohne Zutun um die Seitenverhältnisse von responsive Bildern, auf der anderen Seite hast Du, wenn Du diese Dinge manuell übernimmst, einfach mehr Kontrolle. So kannst Du u.A. den Threshold für das Preloaden Deiner Bilder selbst bestimmen, was bei AMP nicht möglich ist. 

Ich hoffe Dir durch dieses anschauliche Beispiel die Entscheidung, welches System Du verwenden möchtest, erleichtert zu haben.

Tiny technicians with network cables
Kleine technicians with network cablesKirill_M/Photodune.

Danke an Michael Cavalea für das exzellente Skript. Um mehr über Layzr zu erfahren, besuche die GitHub Seite: https://github.com/callmecavs/layzr.js

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.