Responsive Images in WP 4.4: Ein paar Handgriffe fehlen noch …

In WordPress 4.4 erschien ein tolles neues Feature – die Ausgabe von responsiven Bildern. Innerhalb des img-Tags werden neu zusätzlich die Attribute srcset und sizes hinzugefügt. Das ganze funktioniert vollautomatisch und benötigt keine Konfigurationen. Oder doch? Für den Theme Entwickler oder den versierten Benutzer gibt’s noch ein bisschen was zu tun.

Responsive Bilder

Was bedeutet Responsive Images? Anfangs gaben wir uns damit zufrieden, wenn sich die Grösse unseres Bildes dem Container, indem es sich befindet, anpasst:

img {
  height: auto;
  max-width: 100%;
}

In diesem Fall laden wir aber generell ein grosses Bild für sämtliche Bildschirmgrössen. Dazu kommt, dass für die Unterstützung von hochauflösenden Bildschirmen (z.B. Retina Display) ein 2mal grösseres Bild, als der dafür vorgesehene Platz, verwendet wird. Dieses Verfahren nennt sich Downsampling und man erhöht dabei die Pixeldichte eines Bildes.

Ihr seht die Problematik – die Datenmenge, insbesondere für kleinere, mobil genutzte Geräte ist zu gross. Ein Benutzer, der zulange auf den Seitenaufbau warten muss, ist schneller weg als einem lieb ist. Eine gute Performance ist auch für das Suchmaschinen-Ranking immer wichtiger geworden.

Responsive Bilder heisst also weit mehr als nur eine Anpassung per CSS. Es steht für das Laden eines Bildes in geeigneter Grösse je nach Bildschirmeigenschaften des benutzten Geräts.

WordPress 4.4

Im WordPress Release 4.4 wurde ein Teil des Plugins RICG Responsive Images in den Core übernommen. Bildern, zu denen es alternative Bildgrössen gibt, werden neu automatisch mit dem srcset und dem sizes Attribut ergänzt. Dies gilt für alle bereits verwendeten Bilder ohne, dass irgendetwas unternommen werden muss. Es müssen keine Einstellungen im Backend vorgenommen werden.

Die beiden neuen Attribute srcset und sizes sind voneinander abhängig und funktionieren einzeln nicht.

Browserunterstützung

Bis und mit Internet Explorer 11 unterstützen die neuen Attribute leider nicht. Mehr zum Support auf caniuse.com. Dies ist aber nicht tragisch da die Attribute schlicht ignoriert werden, wenn sie nicht unterstützt werden. Wem das nicht reicht, installiert sich das oben erwähnte Plugin, welches weiterhin existiert. Damit wird das Picturefill Skript geladen um eben auch solche Browser zu unterstützen.

Das srcset Attribut

Wie du sicher weisst, kannst du in den Einstellungen von WordPress drei Standard-Bildgrössen definieren. Beim Hochladen eines Bildes werden automatisch Duplikate mit diesen definierten Dimensionen auf dem Server abgelegt. Seit WordPress 4.4 ist noch eine fixe Bildgrösse mit 768px Breite hinzugekommen. Diese ist, da sie nicht veränderbar ist, nicht in den Einstellungen ersichtlich.

Nun was hat dies mit dem neuen Attribut zu tun? Innerhalb des srcset Attribut werden mögliche alternative Bilddateien mit demselben Bild, aber unterschiedlicher Grösse, angegeben. Diese alternativen Bildgrössen können, wie oben beschrieben, in den Einstellungen festgelegt werden. Zusätzlich wird die Breite der jeweiligen Bilddatei in Pixeln, mit dem Buchstaben w, hinzugeschrieben. Dies könnte wie folgt aussehen:

srcset="http://domain.com/wp-content/uploads/2016/03/image_name-300x169.jpg 300w, 
http://domain.com/wp-content/uploads/2016/03/image_name-768x432.jpg 768w, 
http://domain.com/wp-content/uploads/2016/03/image_name-1024x576.jpg 1024w"

Zusätzlich zu dieser Auswahl möglicher Bildgrössen kennt der Browser

  • die Dimension des Viewports,
  • sowie die Bildschirmauflösung.

Der Browser kann nun aus einer Auswahl wählen und entscheidet selbstständig welche der zur Verfügung Grössenvariante geladen wird.

Das sizes Attribut

Was dem Browser nun noch fehlt, ist die Grösse in der das Bild platziert werden soll. Dies erreichen wir mit Media Queries und dem sizes Attribut.

Das sizes Attribut ist abhängig vom Theme-Design und den angewendeten Breakpoints. Da das eine Attribut nicht ohne das andere funktioniert, lädt WordPress eine Standard-Grössenregel. Diese sieht wie folgt aus:

sizes="(max-width: {{image-width}}px) 100vw, {{image-width}}px"

Wenn wir als Beispiel ein 1200px breites Bild einsetzen, würde dies mit dieser Vorgabe folgendes bedeuten: Bis zu einer maximalen Viewportbreite von 1200px entspricht die Bildbreite der Viewportbreite. Ist der Viewport breiter als 1200px wird das Bild mit der Breite von 1200px berechnet.

sizes="(max-width: 1200px) 100vw, 1200px"

Mit diesen Angaben würde ein 1200px breites Bild in einem 1400px breiten Viewport auch mit einer Breite von 1200px berechnet. Auf dem Gerät mit einem Viewport von 1400px wird das Layout aber vielleicht nicht mehr die volle Breite des Bildschirms benötigen. Dazu kommt, dass das Layout höchstwahrscheinlich in mehreren Spalten aufgeteilt ist. Unter diesen Umständen wird der Browser mit der Standard sizes Regel wahrscheinlich kein kleineres Bild, welches unter srcset gelistet ist, wählen.

Schreibweisung und Reihenfolge

  • Es können beliebig viele Media Queries verwendet werden.
  • Nach dem Media Query folgt immer die berechnende Breite. Diese Breite kann mit der Einheit vw (für die Viewportbreite) oder mit px, em, rem angegeben werden. Eine Berechnung mit der CSS calc() Funktion ist auch möglich.
  • Der Browser überprüft die Media Queries der Reihe nach bis einer passt. Danach werden die restlichen ignoriert.
  • An letzter Stelle wird kein Media Query mehr benötigt, da dies der letzt möglichen Bedingung entspricht.

Theme-Anpassungen am Beispiel von Penguin

Nun möchten wir die Ausgabe des sizes Attribut dem Theme anpassen. Dies erreichen wir mit zwei verschiedenen Filter Hooks. wp_calculate_image_sizes benötigen für die Bilder innerhalb der Beiträge, wp_get_attachment_image_attributes benötigen wir für die Beitragsbilder.

Ich stelle mir folgende Fragen:

  1. Welche Breakpoints wendet das Theme in welchen Templates an?
  2. Wie lässt sich die maximale Bildbreite in den verschiedenen Breakpoints berechnen?

Als praktisches Beispiel nehme ich unser WPZOO Theme Penguin. Dieses Feature wird im Release 0.2 von Penguin erscheinen.

Inhaltsbilder (wp_calculate_image_sizes)

Breakpoints in index.php, search.php & archive.php

Mit diesen Breakpoints habe ich folgende Berechnungen gemacht:

(max-width: 599px) calc(100vw - 50px), (max-width: 767px) calc(100vw - 70px), (max-width: 991px) 429px, (max-width: 1199px) 637px, 354px

Breakpoints in single.php

Die Breakpoints der Einzelbeitrags-Ansicht sind ähnlich. Die Unterschiede sind:

  • Ab einem Viewport von 992px ist der Abstand (margin) zum Beitragscontainer 50px anstatt 30px.
  • Ab einem Viewport von 1200px besteht das Layout aus zwei anstatt drei Spalten. Der Beitragsinhalt ist 747px breit.
(max-width: 599px) calc(100vw - 50px), (max-width: 767px) calc(100vw - 70px), (max-width: 991px) 429px, (max-width: 1199px) 597px, 747px

Breakpoints in page-fullwidth.php

Penguin Gold enthält das zusätzliches Page Template page-fullwidth.php. Dieses enthält keine Seitenleiste und zeigt den Inhalt über die ganze Breite.

(max-width: 599px) calc(100vw - 50px), (max-width: 767px) calc(100vw - 70px), (max-width: 991px) 679px, (max-width: 1199px) 839px, 1039px

Function in der functions.php

Somit haben wir die drei verschiedenen Layout-Möglichkeiten. Nun bringen wir das ganze in eine Function, welche die verschiedenen Bedingungen überprüft und das entsprechende sizes Attribut austauscht.

<?php
function penguin_content_image_sizes_attr($size) {
// Singular posts with sidebar
if ( is_singular() ) {
return '(max-width: 599px) calc(100vw - 50px), (max-width: 767px) calc(100vw - 70px), (max-width: 991px) 429px, (max-width: 1199px) 597px, 747px';
}
// Page full width without sidebar
if ( get_page_template_slug() === 'page-fullwidth.php' ) {
return '(max-width: 599px) calc(100vw - 50px), (max-width: 767px) calc(100vw - 70px), (max-width: 991px) 679px, (max-width: 1199px) 839px, 1039px';
}
// 2 col blog with sidebar
else {
return '(max-width: 599px) calc(100vw - 50px), (max-width: 767px) calc(100vw - 70px), (max-width: 991px) 429px, (max-width: 1199px) 637px, 354px';
}
}
add_filter('wp_calculate_image_sizes', 'penguin_content_image_sizes_attr', 10 , 2);
?>

Beitragsbilder (wp_get_attachment_image_attributes)

Das sizes Attribut der Beitragsbilder muss in einer separaten Function definiert werden. Die Breakpoints sind gleich wie bei den Inhaltsbildern.

Function in der functions.php

<?php
function penguin_post_thumbnail_sizes_attr( $attr, $attachment, $size ) {
if ( 'Penguin800X400' === $size ) {
$attr['sizes'] = '(max-width: 767px) calc(100vw - 30px), (max-width: 991px) 469px, (max-width: 1199px) 696.5px, 414px';
}
if ( 'Penguin800X400' === $size && ( is_sticky() ) ) {
$attr['sizes'] = '(max-width: 767px) calc(100vw - 30px), (max-width: 991px) 469px, (max-width: 1199px) 696.5px, 846.5px';
}
if ( 'full' === $size && ( is_singular() ) ) {
$attr['sizes'] = '100vw';
}
return $attr;
}
add_filter( 'wp_get_attachment_image_attributes', 'penguin_post_thumbnail_sizes_attr', 10 , 3 );
?>

Testen

Responsive Images Test Chrome Dev Tools

Für das Testen nutze ich die Chrome Entwicklertools. Damit kann der Device Mode aktiviert werden (1). Unter Elements wird der HTML-Code der Seite angezeigt.

Wenn mit der Maus über den src Link oder die srcset Links gefahren wird, erscheint ein Popup-Fenster (2). Darin wird die Grösse angegeben in der das Bild berechnet wird. Falls die berechnete Grösse nicht genau dem des sizes Attribut entspricht, erscheint diese zusätzlich in Klammern.

Falls der Link unterhalb des Mauszeigers nicht dem geladenen Bild entspricht, wird die geladene Quelle angezeigt (currentSrc). Das ist also die Variante die der Browser aus der srcset Auswahl gewählt hat.

Responsive Images Test Chrome Dev Tools Network

Unter Network kann ebenfalls überprüft werden, welche Grössenvariante des Bildes geladen wurde.

Achtung: Hat der Browser vorgängig eine grössere Variante als benötigt geladen, wird sie vom Browser-Cache geholt und nicht neu geladen. Daher empfiehlt sich der Cache zu deaktivieren (siehe Markierung).

Links & Credits

Hier ein paar Quellen, die mir halfen das Thema besser zu verstehen:

Das Beitragsbild habe ich mithilfe der folgenden Quellen erstellt:

Du bist gefragt: Konnte ich dir Responsive Images in WordPress etwas näher bringen? Hast du einen Fehler entdeckt? Würdest du bei der aufgezeigten Penguin-Lösung etwas anders machen?