Ein Problem im Responsive Webdesign ist es weiterhin Bilder in optimierten Bilddimensionen zur Verfügung zu stellen. Mit der CSS-Anweisung
img { max-width: 100%; height: auto; } |
lassen sich zwar Bilder „responsive“ gestalten, allerdings bleibt die Datenmenge gleich. Lädt man z.B. ein sehr großes Bild, das dann auf kleinen Bildschirmen angezeigt wird, muss man unter Umständen zu viele Bilddaten herunterladen und wartet je nach Verbindungsgeschwindigkeit recht lang. Optimal wäre es mehrere Bilder für die jeweiligen Bildschirmgrößen zur Verfügung zu stellen und immer das passende Bild zu laden. Die Browser sind dafür leider nicht ausgelegt und es gibt auch kein Bildformat, dass das unterstützt. Andere Lösungswege müssen also gefunden werden.
Lösung über <noscript>
Eine gute Lösung der Problematik basiert auf der <noscript>-Methode mit HTML5 data-Attributen. Hierbei wird das Bild in ein <noscript>-Wrapper mit den Attributen data-large, data-small und data-alt gepackt. Diese Attribute beinhalten die Pfade zur großen und kleinen Bild-Version und den Alternativ-Text. Ein Beispiel auf http://www.monoliitti.com/images/
<noscript data-large="Koala.jpg" data-small="Koala-small.jpg" data-alt="Koala"> <img src="Koala-small.jpg" alt="Koala" /> </noscript> |
Der Vorteil an der Lösung: Assets die im <noscript>-Tag eingebunden sind, werden vom Browser nicht in das DOM eingefügt (und geladen) wenn JavaScript aktiviert ist. Ressourcen werden also nicht doppelt geladen. Mit JavaScript, wir nehmen mal jQuery zur Hilfe, können wir nun die Pfade je nach Bildschirmgröße in das scr-Attribut des Bildes einfügen und außerhalb des <noscript>-Wrapper hinzufügen.
$('noscript[data-large][data-small]').each(function(){ var $this = $(this); var src = screen.width >= 480 ? $this.data('large') : $this.data('small'); $('<img src="' + src + '" alt="' + $(this) .data('alt') + '" />') .insertAfter($this); }); |
Umsetzung in TYPO3
Das ist eine einfache Lösung, die man mit TYPO3-Bordmitteln, also mit TypoScript umsetzen kann.
#adaptive images lib for TYPO3 lib.adaptive-images = COA lib.adaptive-images { 1 = TEXT 1.value = <figure class="csc-textpic-imagecolumn###CLASSES###"><noscript 10 = IMG_RESOURCE 10 { file.import.current = 1 file.maxW = 480 file.override.data = {$styles.content.imgtext.maxW} stdWrap.noTrimWrap = | data-small="|" | } 20 = IMG_RESOURCE 20 { file.import.current = 1 file.maxW = {$styles.content.imgtext.maxW} file.override.data = register:maxImageWidth stdWrap.noTrimWrap = | data-large="|" | } 1000 = TEXT 1000.value = >|</noscript>###CAPTION###</figure> } |
Überschreiben der Wrapper im tt_content.image-Objekt
tt_content.image.20 { rendering { singleNoCaption { singleStdWrap.wrap.override.cObject < lib.adaptive-images } noCaption { singleStdWrap.wrap.override.cObject < lib.adaptive-images } singleCaption { singleStdWrap.wrap.override.cObject < lib.adaptive-images } splitCaption { singleStdWrap.wrap.override.cObject < lib.adaptive-images } globalCaption { singleStdWrap.wrap.override.cObject < lib.adaptive-images } } } |
Ein Umsetzung für TYPO3 4.5/4.6 findet man in den Slides Responsive TYPO3.
TYPO3-Extension für Adaptive Images
Die <noscript>-Methode als Vorbild nutzt auch die TYPO3-Extension rtp_imgquery, die allerdings nicht im öffentlichen TER, sondern aktuell noch als beta auf Github zu finden ist. In den Konstanten legt man die Default-Breakpoints fest:
#typoscript constants styles.content.breakpoints.style = styles.content.breakpoints = 600:500, 400:280, 320:160 styles.content.breakpoints.default = 980 |
Zudem bringt die Extension einen Fluid-Viewhelper mit und kann mit anderen Rendering-Engines wie Smarty umgehen. Ein weiterer Vorteil der Extension ist, dass sie keinerlei Unterstützung durch externen JavaScript-Bibliotheken wie jQuery benötigt, sondern mit nativen JavaScript funktioniert. Außerdem kann der Redakteur die vordefinierten Breakpoints im Inhaltselement nochmals überschreiben falls es notwendig ist. Nachteilig finde ich allerdings, dass CSS über ein style-Attribut ins HTML eingefügt wird (das ich in der Beispiel-Konfiguration oben durch ’styles.content.breakpoints.style =‘ entfernt habe) und Javascript direkt danach ins HTML eingebunden wird, was zu Performance-Problemen führen kann.
adaptive-images.com Script mit TYPO3 verwenden
Eine Alternative ist die Lösung von adaptive-images.com (woher der Name für die Technik auch stammt). Diese Lösung ist zudem komplett unabhängig vom TYPO3 CMS. Das PHP-Script generiert automatisch anhand der Screengröße für die unterschiedlichen Breakpoints ein neues Bild von der verlinkten Ressource und legt das auf dem Server ab. Es sind keinerlei Änderungen an der HTML-Struktur notwendig.
Wie in der Anleitung auf adaptive-images.com beschrieben, fügt man die PHP-Datei in das Root-Verzeichnis des Servers hinzu und legt ein Verzeichnis (‚ai-cache‘) für die Bild-Caches an und vergibt Schreibrechte.
Im <head> muss nun das JS-Schnipsel für das Setzen des Screen-Resolution-Cookie eingebunden werden. In der Anleitung auf adaptive-images.com ist der Hinweis, dass das Cookie so früh wie möglich gesetzt werden soll, also so weit oben wie möglich in den <head>-bereich eingefügt werden.
#TypoScript setup page.headTag ( <head> <script> document.cookie='resolution='+Math.max(screen.width,screen.height)+'; path=/'; </script> ) |
Die Überschreibung des <head>-Tag ist die frühestmögliche Stelle in TYPO3. Im PHP-Script (adaptive-images.php) müssen nun die Breakpoints angepasst werden.
$resolutions = array(1382, 992, 768, 480, 320); |
Das .htaccess-Script in TYPO3 muss angepasst wie folgt werden:
<IfModule mod_rewrite.c> # Enable URL rewriting RewriteEngine On Options +FollowSymlinks # Adaptive Images # don't apply the AI behaviour to images inside AI's cache folder: RewriteCond %{REQUEST_URI} !ai-cache # further directories that shouldn't use AI RewriteCond %{REQUEST_URI} !fileadmin/images # Send any GIF, JPG, or PNG request that IS NOT stored inside # one of the above directories RewriteRule ^.*\.(jpg|jpeg|png|gif)$ adaptive-images.php [L] . . . </IfModule> |
Danke an Bastian Guse für die Hilfe bei der Anpassung des htaccess-Script.
Funktionsweise
Im Cookie wird beim Aufruf die maximale Bildschirmgröße gesetzt, bedeutet z.B. beim iPad mini (768 x 1024px) wird 1024 gespeichert, beim alten iPhone 3GS (320 x 480px) wird 480 gespeichert. Durch die Anpassungen in der htaccess-Datei werden nun alle Anfragen für Bildressourcen (jpg|jpeg|png|gif) durch die PHP-Datei geschleust. In dieser Datei wird anhand des Cookies entschieden welche Bildgröße benötigt wird. Beim ersten Aufruf wird das Bild in der benötigten Bildgröße durch die Server Bibliothek ‚GD lib‘ erstellt und in das laut Breakpoint-Arrays passende Cache-Verzeichnis ‚ai-cache/Bildgröße/‘ gespeichert. Beim zweiten Aufruf wird das vorhandene Bild sofort zurück gegeben und nicht erneut prozessiert. Das Prozessieren der Bilder wird auch nur für die Bilder gemacht, die größer als die Screen-Width sind (nicht zu verwechseln mit dem Viewport des Browsers). Beim iPhone 5 werden z.B. 1136, beim Nexus 4 1280 gespeichert. Bilder die nun mit 1000px in die Seite eingebunden sind, werden für das iPhone 5 oder Nexus 4 nicht prozessiert, auch wenn der Viewport der Geräte im Portrait-Modus 320px bzw. 383px beträgt. Ich bin noch unentschlossen, ob das gut oder schlecht ist. Einerseits hat man so ein Retina-optimiertes Bild auf diesen Devices, andererseits ist das Bilddatenmenge trotzdem relativ hoch. Des Weiteren ist ein individuelle Anpassung durch den TYPO3-Redakteur leider nicht möglich.
Die Lösungen sind relativ einfach in TYPO3 integrierbar, löst allerdings nicht das eigentliche Problem, das in Zukunft das HTML5-Element <picture> besser machen soll. Auch löst nur das PHP-Script von adaptive-images.com die Problematik mit hochauflösenden Bildern und das auch nur bedingt zufriedenstellend. Wie man Retina-optimierte Bilder von TYPO3 automatisch generieren lässt, habe ich im Artikel „TYPO3 Retina Images“ beschrieben. Weitere Tipps sind immer willkommen.