1. https://www.joinbox.org/blog/handling-von-responsiven-bildern-drupal Handling von responsiven Bildern in Drupal
März 2023

Die optimierte Auslieferung von Bildern im Web ist ein Thema, das in unserer Web-Agentur immer wieder heiss diskutiert wird. Wir versuchen ständig, noch bessere Lösungen zu finden, im Bestreben, qualitativ hochwertige Bilder anzuzeigen und gleichzeitig jede Website so performant wie möglich zu halten. Hier zeigen wir, welche Lösungen sich bei uns bewährt haben.

1. Grundlagen: Responsive Images

Die Ausgabe und Konfiguration von responsiven Bildern ist ein breites Feld, welches Themen betrifft wie die Bildauflösung, Dateiformate oder den Ladezeitpunkt («Lazy Loading»). In diesem Artikel liegt der Schwerpunkt auf der Frage, wie auf einer responsiven Website optimierte Bildauflösungen für jede Screengrösse ausgegeben werden können. Dabei werden zuerst im Allgemeinen die entsprechenden HTML-Spezifikationen betrachtet und wie der Browser damit umgeht. Danach wird im Speziellen die Konfiguration im von Joinbox eingesetzten CMS (Content Management System) Drupal behandelt.

In HTML gibt es grob gesehen zwei Konzepte im Zusammenhang mit responsiven Bildern. Diese werden in verschiedenen Artikeln im Web im Detail behandelt (z.B. MDN: Responsive Images). Hier werden sie deshalb nur kurz zusammengefasst beschrieben. Das eine Konzept ist als «Art Direction» bekannt und das andere als «Resolution Switching».

Bei Art Direction geht es im Wesentlichen darum, unterschiedliche Bilder zu nutzen, abhängig von der Viewport-Breite1. Das spielt zum Beispiel dann eine Rolle, wenn man auf Smartphones ein Bild im Hochformat anzeigen möchte, aber auf Desktop-Bildschirmen im Querformat. Oder wenn man auf kleinen Bildschirmen einen anderen, kleineren Ausschnitt eines Bildes zeigen möchte als auf grossen Screens. Art Direction wird mit einem <picture> Element umgesetzt, welches verschiedene <source> Elemente enthält.

Bilddarstellung auf Desktop und Mobile
Beispiel für Art Direction: Auf Mobile wird ein anderer Bildausschnitt dargestellt

Bei Resolution Switching geht es darum, die am besten passende Bildauflösung für die jeweilige Viewport-Breite zu laden. Das ist eine Frage, die bei jedem responsiven Bild eine Rolle spielt und somit viel häufiger von Bedeutung ist als Art Direction. Dieses Konzept wird mithilfe von zwei Attributen auf dem <img> Element implementiert. Mit srcset werden dem Browser die vorhandenen Versionen eines Bildes mitgeteilt, die geladen werden können. Mit sizes kann dem Browser gesagt werden, wie breit ein Bild auf dem Screen unter bestimmten Bedingungen angezeigt wird. Zum Beispiel wird bei einer Liste von Artikeln auf einer Blog-Seite der einzelne Eintrag auf Mobile über die ganze Breite angezeigt (100vw), auf Tablets in zwei Spalten (50vw) und auf Desktop-Screens in drei Spalten (33vw). Aus den Angaben der beiden Attribute sizes und srcset berechnet dann der Browser selbständig, welches Bild er in welcher Situation laden soll. So wird sichergestellt, dass immer die optimale Bildqualität für das jeweilige Gerät geladen wird.

Resolution Switching kann auch mit <picture> und <source> umgesetzt werden. Der Unterschied ist, dass dann die umsetzende Person vorgibt, wann welches Bild geladen wird und nicht der Browser selbst.

Für die Thematik dieses Artikels ist das Konzept von Resolution Switching mit den beiden Attributen srcset und size relevant, weil es eine flexiblere und effizientere Lösung für responsive Bilder bietet.

2. Sinnvolle Werte für srcset und sizes

Die beiden Attribute srcset und sizes enthalten Listen mit Werten und Angaben. Deren Komplexität und die vielen Zahlen können verwirrend sein. Wie also können konkrete und sinnvolle Werte für diese zwei Attribute ermittelt werden? Eine Vorgehensweise, die sich bei uns bewährt hat, möchte ich hier erläutern. Betrachten wir dazu als Beispiel die News-Übersicht bei unserem Kundenprojekt RONDO.

Bildbreite in zweispaltigem Layout
Bildbreite bei einer Viewport-Breite von 839px
Bildbreite in dreispaltigem Layout
Bildbreite bei einer Viewport-Breite von 840px

Ich erstelle als erstes eine Tabelle mit den Breakpoints der Komponente. Hier sind diese bei 600px und 840px. Unter 600px wird eine Spalte dargestellt, ab 600px sind es zwei und ab 840px drei Spalten. Dann füge ich jeweils den Wert hinzu, der 1px unter diesen Breakpoints liegt, also 599px und 839px. Auf diesen Viewport-Breiten wird das Bild in der grössten Version des jeweiligen Layouts dargestellt. Zuoberst ergänze ich die Viewport-Breite, bei der das gesamte Seitenlayout nicht mehr wächst (hier 1312px). Ab hier verändert sich die Grösse des Bildes nicht mehr. Zuunterst füge ich noch den Wert ein, der die kleinste Version des Bildes repräsentiert, die generiert werden soll. Das ergibt dann in diesem Fall eine Tabelle mit sechs Viewport-Breiten.

Für jeden dieser Werte schaue ich dann, wie gross das jeweilige Bild ausgegeben wird2. Jeden dieser Werte verdopple ich, um zu sehen, welche Grösse Bildschirme mit einer doppelten Pixeldichte benötigen. Ist diese Tabelle fertig ausgefüllt, sehe ich, welche minimalen und maximalen Bildgrössen benutzt werden.

Tabelle mit Bildgrössen auf verschiedenen Viewport-Breiten

Anschliessend schreibe ich alle diese Werte der Grösse nach untereinander und versuche Gruppierungen zu finden, die man zu einer Bildgrösse zusammenfassen könnte. Der grösste Wert jeder Gruppe wird jeweils die Bildgrösse, die ich erstellen möchte. Dabei kann ich immer noch einmal zusammenfassen. Im vorliegenden Fall könnte man zum Beispiel 570px weglassen und durch die 800px-Version abdecken lassen3.

Tabelle mit zu erstellenden Bildgrössen

Sagen wir also, dass wir vier Grössen des Bildes erstellen, mit den Breiten 270px, 400px, 800px und 1200px. Im srcset Attribut wird dann eine kommagetrennte Liste dieser Bilder angegeben mit dem jeweiligen Dateipfad und -namen sowie der Breite, die diese Version hat. Das Format der Breitenangabe besteht aus dem Pixelwert, gefolgt von einem w (für width). Konkret würde das im vorliegenden Beispiel also folgendermassen aussehen:

srcset=”image-270.jpg 270w, image-400.jpg 400w, image-800.jpg 800w, image-1200.jpg 1200w”

Um den Wert für das sizes Attribut zu finden, listen wir die Media-Queries, welche die Breakpoints abbilden, auf und ergänzen diese mit der jeweiligen Breite des Bildes. Da die Bilder responsive sind, geben wir die Breite sinnvollerweise in vw an, also in Prozent der Viewport-Breite. Erst wenn das Seitenlayout nicht mehr mit dem Viewport mitwächst, bleibt auch die Breite des Bildes gleich und wir können einen fixen Pixel-Wert angeben.

  • 100vw (1 Spalte)
  • (min-width: 600px) 50vw (2 Spalten)
  • (min-width: 840px) 33vw (3 Spalten)
  • (min-width: 1312px) 400px (Seitenlayout wächst nicht mehr weiter)

Diese Werte werden nun als kommagetrennte Liste ins sizes Attribut geschrieben. Dabei gilt es zu beachten, dass der Browser die Liste von links nach rechts liest und sobald eine Bedingung zutrifft, der entsprechende Wert genommen und die Liste nicht weiter durchlaufen wird. Die Reihenfolge der Listen-Einträge ist also wichtig.

Der Defaultwert – also der Wert, der genommen werden soll, wenn kein anderes Media-Query zutrifft – wird mit dem letzten Eintrag angegeben. Konkret sieht das dann so aus:

sizes=”(min-width: 1312px) 400px, (min-width: 840px) 33vw, (min-width: 600px) 50vw, 100vw”

3. Konfiguration in Drupal

Nun haben wir sinnvolle Werte für die srcset und sizes Attribute ermittelt. Schreibt man das HTML selber, kann man diese direkt so anwenden. Bei der Arbeit mit Drupal werden das Markup eines Bildes und insbesondere dessen Attribute von einem Modul zusammengestellt und ausgegeben. Diese Ausgabe kann man mit Konfigurationen beeinflussen. Davon betroffen sind die folgenden drei Core-Module:

  • Image (image)
  • Responsive Image (responsive_image)
  • Media Library (media_library)

Die schlussendliche Ausgabe wird dann auf der Entity über «Anzeige verwalten» gesteuert.

Die Bildgrössen, die wir oben für srcset definiert haben, werden im Image Modul als Bildstile erstellt: Konfiguration > Media > Bildstile (/admin/config/media/image-styles). Auf «Bildstil hinzufügen» klicken und Namen eingeben. Dann bei der Sektion «Effekte» den Effekt «Skalieren» auswählen und hinzufügen4. Wir erstellen jeweils einen Bildstil für jede Bildgrösse, die im srcset erscheinen soll.

Als nächstes konfigurieren wir das Responsive Image Modul: Konfiguration > Media > Responsive Bildstile (/admin/config/media/responsive-image-style). Mit einem Klick auf «Responsiven Bildstil hinzufügen» erstellen wir eine neue Konfiguration für die News-Übersicht. Bei «Breakpoint-Gruppe» muss eine Breakpoint-Konfiguration ausgewählt werden. Da wir bei Joinbox nicht mit der Breakpoint-Konfiguration von Drupal arbeiten, benutzen wir hier die Default-Gruppe vom Responsive Image Modul. Diese enthält nur einen Breakpoint, seine Konfigurationen werden also für alle Bildschirmgrössen gültig sein. Unter dem jeweiligen Breakpoint (der Default-Breakpoint von Responsive Image ist angeschrieben mit «1x Viewport Sizing []») kann der responsive Bildstil konfiguriert werden. Wir wählen hier bei Type «Mehrere Bildstile auswählen und das Sizes-Attribut verwenden». Dann kann man diejenigen Bildstile aus dem Image Modul auswählen, die man hier verwenden möchte. Bei «Größen» kann eins zu eins der Wert für das sizes Attribut eingetragen werden, wie wir ihn oben erarbeitet haben.

Screenshot der Drupal Konfigurationsseite für das Responsive Image Modul
Konfiguration des Responsive Image Moduls

Nun gehen wir einen Schritt weiter in die Media-Library: Struktur > Medientypen (/admin/structure/media). Die oben definierten responsiven Bildstile können nun bei «Anzeige verwalten» des betroffenen Medientyps ausgewählt werden. Falls verschiedene Ausgaben von einem Bild möglich sein sollen, kann man hier verschiedene View Modes dafür erstellen. Zum Beispiel einen für die Ausgabe in der News-Übersicht und einen anderen für die Ausgabe auf der News-Detailseite. Bei beiden View Modes können dann unterschiedliche responsive Bildstile ausgewählt werden – insbesondere der Wert für das sizes Attribut wird hier ein anderer sein.

Screenshot der Drupal Konfigurationsseite für die Ansicht des Media-Types
Konfiguration der Anzeige des Media-Types

Damit kommen wir zum letzten Schritt, nämlich zur Konfiguration des Inhaltstyps: Struktur > Inhaltstypen (/admin/structure/types). Die Bilder aus der Media-Library werden hier referenziert und die Ausgabe ebenfalls unter «Anzeige verwalten» geregelt. Auch hier wird es je einen View Mode geben für die Ausgabe in der Übersicht und diejenige auf der Detailseite. Bei der Referenz auf das Bild aus der Media-Library kann der View Mode des Mediums ausgewählt werden, und zwar derjenige, welcher dem View Mode des Inhaltstyps entspricht.

4. Debugging

Das Debugging von responsiven Bildern im Browser ist nicht ganz banal. Es geht darum, zu untersuchen, welche Bildgrösse der Browser geladen hat. Um dies herauszufinden, ist die Vorgehensweise je nach Browser unterschiedlich. In diesem Artikel werden Chrome und Firefox behandelt, sowie ein JS-Snippet vorgestellt, welches die gewollten Angaben in der Konsole ausgibt.

Von Interesse sind insbesondere zwei Werte:

  • die tatsächlich dargestellte Breite des Bildes (im Folgenden «dargestellte Breite»)
  • die Breite des geladenen Bildes (im Folgenden «geladene Breite»)

Ebenfalls interessant fürs Debugging ist die Breite des Bildes, wie sie anhand des sizes Attributes sowie der aktuellen Viewport-Breite berechnet wurde (im Folgenden «angegebene Breite»). Dieser Wert sollte (in etwa) gleich gross sein, wie die tatsächlich dargestellte Breite des Bildes. Ist dies nicht der Fall, weist das darauf hin, dass die Konfiguration im sizes Attribut falsch oder zu ungenau ist. Eine saubere sizes-Definition ist wichtig, weil der Browser sich bei der Auswahl der zu ladenden Bildgrösse auf diese Angaben verlässt.

Mit diesen Werten lässt sich feststellen, ob der Browser sich so verhält, wie man es erwarten würde, respektiv ob man die Werte für srcset und sizes richtig konfiguriert hat.

In Chrome findet man die gewünschten Angaben, wenn man im Inspektor über die URL im <img> Element hovert. Im Overlay, das sich dann öffnet, wird die dargestellte Breite mit «Gerenderte Größe» beschrieben und die geladene Breite mit «Intrinsische Größe».

Screenshot vom Debugging in Chrome im Inspector
Bilder-Debugging im Chrome Tab «Inspektor»

In Firefox wird die dargestellte Breite direkt beim Bild angezeigt, wenn man im Inspektor über das <img> Element hovert. Das Overlay, das sich dabei öffnet, zeigt die angegebene Breite an. Die geladene Breite findet man im Netzwerk-Tab in den Dev-Tools, wenn man über den Eintrag für das geladene Bild hovert.

Screenshot vom Debugging in Firefox im Inspector
Bilder-Debugging im Firefox Tab «Inspektor» für die «dargestellte Breite» und «angegebene Breite»
Screenshot vom Debugging in Firefox in der Netzwerkanalyse
Bilder-Debugging im Firefox Tab «Netzwerkanalyse» für die «geladene Breite»

Eine interessante Variante, um alle gewünschten Werte an einem Ort anzuzeigen, ist ein JS-Script, welches Oliver Ash auf GitHub veröffentlicht hat. Maxim Orlov machte daraus ein handliches Snippet, welches einfach im Source-Code eingefügt werden kann, um sich die Angaben für ein einzelnes Bild in der JS-Konsole anzeigen zu lassen.

Zusammenfassung Bilder-Debugging

zusammenfassende Tabelle zu Bilder-Debugging

Alles klar?

Will man das Bilder-Handling sauber machen und die Fähigkeiten des Browsers ausnützen, bedeutet das einiges an Mehraufwand, als wenn man einfach ein <img> Element mit einer einzigen Source einfügt. Aber es lohnt sich definitiv, wenn dafür auf einem Smartphone mit schlechter Verbindung die Bilder schneller geladen werden oder wenn auch auf einem grossen Screen die Bilder scharf dargestellt werden.

Wenn du Fragen oder Rückmeldungen zu dem Thema hast, melde dich bei Andi!