Mobile Geräte mit Retina / HDPI Display sind heutzutage Standard. Ein Grund mehr auf einer neuen Website Bildmaterial zur verfügung zu stellen, welches diese Technik bedienen kann – macht man dies nicht, wirken Grafiken und Bilder unscharf. Aber wie zum Teufel soll man das vernünftig anstellen?
Es ist egal ob man ein CMS wie TYPO3 verwendet oder eine einfache statische HTML Seite hat, das Problem bleibt gleich. Die ausgelieferten Bilder sollten zugunsten der Ladegeschwindigkeit nur so groß sein, wie sie tatsächlich benötigt werden. Sind die Bilder größer verursacht das unnötige Datenübertragung, verlangsamt den Seitenaufbau / die Darstellung und wirkt sich ebenfalls negativ auf ein Google Page Speed Ranking aus.
CSS
Innerhalb CSS hat man diese Problematik nicht. Durch Media-Querys können wir ganz einfach zwischen normalem und Retina- / HDPI-Display unterscheiden und so andere Hintergrundgrafiken verwenden.
@media only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 13/10), only screen and (min-resolution: 120dpi) { /* Retina / HDPI Background Images */ }
Doch wie sollte man normale Bilder (<img>) ausliefern?
Serverseitig mit PHP?
Aktuell gibt es keine richtige Möglichkeit um auf Serverseite herauszufinden ob es sich um ein hochauflösendes Gerät handelt. An dieser Stelle frage ich mich allerdings: Warum wird das nicht über den User-Agent oder einem anderen Parameter übermittelt? Der Stand der Technik würde genau diese Informationen (Auflösung in DPI, Screengröße in Pixel) dringend benötigen um sofort entscheiden zu können, welches Bild in welcher Größe ausgeliefert werden muss.
So ist es leider – derzeit gibt es keine Möglichkeit dazu. Auch wenn ich (wie viele andere sicher auch) lange darüber nachdenken wie man das Zustande bekommen könnte.
Eine Lösung
Eine Lösung die ich gezwungener Maßen in ein TYPO3 Projekt einbinden musste und welche mittlerweile auch unter Google recht verbreitet ist:
- erstelle beim ersten Pageload via JavaScript einen Cookie der genau diese Daten beinhaltet
- führe via JavaScript einen Refresh der Seite (gleiche URL) aus sofern der Cookie nicht schon existiert
- lies auf Serverseite den Cookie aus
Allerdings finde ich diese Methode nach wie vor fraglich, denn erstens finde ich einen Redirect beim ersten Aufruf blöd (vor allem wenn ich an mobile Geräte denke), zweitens wird Google davon mit hoher Wahrscheinlichkeit auch nicht begeistert sein und drittens fällt schon der Google Page Speed check flach, weil er eine Dauerschleife ankündigt.
Also eher doch keine Lösung? Doch, eine Alternative gibt es zumindest via …
JavaScript
Es gibt ein kleines JavaScript Tool namens Retina.js. Mit dem Tool wird geprüft, ob es sich um ein hochauflösendes Gerät handelt. Wenn ja, wird bei jedem Bild gecheckt, ob es davon eine High-Resolution Variante gibt (@2x). Gibt es eine, wird die Bildquelle ausgetauscht und das hochauflösende Bild wird angezeigt. An sich ganz gut – allerdings funktioniert das nicht mit TYPO3, wenn Bilder dynamisch auf entsprechende Größe generiert werden, denn TYPO3 kennt kein @2x Anhängsel beim Image-Rendering.
HTML 5 – Data-Attribute & JavaScript
Eine minimalistische Selfmade-Technik habe ich auf meiner neuen Website eingebunden. Hinzu kommt an dieser Stelle aber noch, dass es für Geräte unter 580 Pixeln Screenbreite quadratische Bilder geben soll (mit besserem Bildausschnitt für kleinere Screens), für alle größeren Screens normale, rechteckige Bilder. Dabei wird das Bild in „vorhersehbarster“ Version ausgelifert. Das heißt: Typisch für Desktop Browser nicht hochauflösend, rechteckig. Für Tablets hochauflösend, rechteckig und für Smartphones hochauflösend, quadratisch.
In jedem Fall werden sämtliche anderen Versionen (insgesamt vier: rechteckig, rechteckig HD, quadratisch, quadratisch HD) in data-Attribute verpackt. Ein minimales JavaScript sorgt nun dafür zu checken, ob das ausgelieferte Bild dem entspricht welches benötigt wird. Ist das der Fall passiert nichts, ist das nicht der Fall wird das entsprechend passende Bild aus dem jeweiligen data-Attribut als Bild-Quelle verwendet. Das Script reagiert so schnell, dass die vorherigen Bilder nicht einmal mehr geladen werden (<img>-Tags werden komplett entfernt und neu aufgebaut).
So ungefähr sieht das Ganze dann aus:
<div class="dynamic-image" data-imageurlmobilehd="mobilehd.jpg" data-imageurlmobile="mobile.jpg" data-imageurlhd="desktophd.jpg" data-imageurl="desktop.jpg"> <img ... /> </div>
var windowWidth; $(document).ready(function() { windowWidth = $(window).width(); dynamicImages(); }); $(window).resize(function() { windowWidth = $(window).width(); dynamicImages(); }); function dynamicImages() { $('.dynamic-image').each(function() { var imageWrap = $(this); var image = $(imageWrap).children().first(); var imageSrc; if (windowWidth > 580) { if (window.devicePixelRatio >= 2) { imageSrc = $(imageWrap).attr('data-imageurlhd'); } else { imageSrc = $(imageWrap).attr('data-imageurl'); } } else { if (window.devicePixelRatio >= 2) { imageSrc = $(imageWrap).attr('data-imageurlmobilehd'); } else { imageSrc = $(imageWrap).attr('data-imageurlmobile'); } } if (imageSrc != $(image).attr('src')) { var title = $(image).attr('title'); $(image).remove(); $(imageWrap).append('<img src="' + imageSrc + '" title="' + title + '" alt="' + title + '" />'); } }); }
Fazit
Mit dieser Technik bin ich zumindest derzeit recht zufrieden – auch wenn das auch nicht optimal ist. Wirklich perfekt wäre es eben nur, wenn man via PHP (serverseitig) abfragen könnte um was für eine Screen es sich handelt.