Responsive Webdesign mit TYPO3: So nutzt Du Adaptive Images
Ein Problem im Responsive Webdesign ist es weiterhin Bilder in optimierten Bilddimensionen zur Verfügung zu stellen. Mit der folgenden CSS-Anweisung lassen sich Bilder zwar „responsive“ gestalten, allerdings bleibt die Datenmenge gleich.
img {
max-width: 100%;
height: auto;
}
Lädt man zum Beispiel 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 lange. 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. Es müssen also andere Lösungswege 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 sowie den Alternativ-Text. Ein Beispiel findet man 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 integrieren 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>
}
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 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 liefert die Extension einen Fluid-Viewhelper 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 auch der Name für die Technik 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 ein 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. Es empfiehlt sich also, den Cookie so weit oben wie möglich in den <head>-bereich einzufügen.
#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 wie folgt angepasst 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, das bedeutet beispielsweise beim iPad mini (768 x 1024px) wird 1024 gespeichert, beim 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ückgegeben 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 zum Beispiel 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 die 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ösen 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.
Ursprünglich erschienen bei TYPO3Blogger.de
Über den Autor
Sven Wolfermann ist als freier Frontend-Entwickler mit seiner Firma maddesigns für Agenturen und Endkunden tätig. Er berät bei der Umsetzung von Responsive Webdesign, arbeitet mit Webstandards, HTML5, CSS3, jQuery sowie Sass & Compass und ist seit 2009 zertifizierter TYPO3 Integrator.
Oh man, wenn ich das rumgehackte im TypoScript schon wieder sehe, freue ich mich wieder endlich kein TYPO3 mehr entwickeln zu muessen. Was aetzenderes wie TypoScript gibt’s echt nicht.. wobei TYPO3 Flow suckt auch ziemlich :>
Schöne Anleitung – danke!
Ich wäre allerdings dafür, dass TYPO3 endlich von selbst eine moderne Ausgabe erzeugt, ohne alles umschreiben zu müssen.
Warum die Links für die alternativen Auflösungen nicht direkt in den img-Tag packen, statt in einen noscript-Tag?
Noscript-Tags haben den Nachteil, dass sie in XHTML-Dokumenten keine Wirkung haben (sollten).
Siehe: http://stackoverflow.com/questions/2167453/noscript-processing-in-xml-documents
@Simon du kannst die HTML5-Data-Attribute auch direkt ins img-Tag einfügen
# img params
tt_content.image.20.1.params.cObject = COA
tt_content.image.20.1.params.cObject {
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=“|“ |
}
}
noscript hat, wie beschrieben, den Vorteil, dass Assets nicht doppelt geladen werden.
Der verlinkte Stackoverflow-Artikel ist nun über 3 Jahre alt und behandelt die Ausgabe als ‚application/xhtml+xml‘ – das bis einschließlich IE8 nicht unterstützt wird. Ich denke, dass du deine Seite nicht als XHTML+XML renderst, sondern ganz normal als ‚text/html‘. In modernen Browser ist das verhalten wie beschrieben, zudem geht es um die Optimierung für mobile Geräte, die HTML5-Browser sollten das richtig machen.
@Sven
Mir geht es nicht darum ob etwas so funktioniert oder nicht – ich wollte nur darauf hinweisen, dass der Tag „noscript“ in XML-Dokumenten (wie zum Beispiel XHTML) nicht erlaubt ist. Also nur die Validierung des Dokumentes.
Ob die Browser es dann korrekt darstellen hängt von der Fehlertoleranz ab, die bekanntlich sehr hoch ist ;)
Wenn du dein Dokument aber als HTML-Dokument ausgibst, ist dieser Methode nichts entgegen zu setzen.
Mir fällt gerade ein … wäre es nicht möglich, eine Kombination aus deinem Script und dem Attribut „srcset“ zu erstellen..? Nur so als Idee um auch hier auf einen Standard zurückzugreifen…
Danke, Sven, für diese schöne Zusammenstellung für / aus TYPO3-Sicht! Ergänzend möchte ich mir an dieser Stelle erlauben, auf mein gerade veröffentlichtes Projektchen „squeezr“ hinzuweisen. In Bezug auf die Behandlung von Bildern hat mir das oben beschriebene „Adaptive Images“ Modell gestanden, weshalb sich Funktionalität und Einsatz weitgehend decken. Ich war allerdings bemüht, ein paar „Schönheitsfehler“ von AI zu korrigieren, darunter z.B.
– die Tatsache, dass bei AI wirklich *jedes* Bild von PHP behandelt wird, selbst ein solches, das zuvor bereits generiert und gecachet wurde,
– dass AI nur mangelhaft mit den HTTP-Headern arbeitet, die ein Browser braucht, um die Bilder ordentlich lokal zu cachen (mit fatalen Folgen: Bilder, die überhaupt nicht skaliert werden brauchen, werden vom Browser niemals gecachet, und alle anderen erst beim dritten statt beim zweiten Aufruf …),
– u.s.w.
Anders als bei AI findet bei squeezr die Definition der Breakpoints nicht serverseitig, sondern beim Client statt, also im JavaScript bzw. im HTML-Quellcode. Trotzdem ist der Einsatz von squeezr vergleichbar einfach wie oben beschrieben. Daneben plane ich, demnächst eine entsprechende TYPO3-Extension zu veröffentlichen, die einem die Installation und Konfiguration erleichtert / abnimmt.
Neben der Behandlung von Bildern kümmert sich squeezr auch um die Reduktion von überflüssigem CSS, indem er bereits auf dem Server CSS3 Media Queries auswertet und für das jeweils genutzte Gerät irrelevante Passagen entfernt (und optional auch CSS-Minifizierung anwendet). Ausführliche Infos sowie den Download (aktuell in der ersten Beta) gibt’s unter
http://squeezr.it
bzw. bei GitHub unter
https://github.com/jkphl/squeezr
Ich würde mich sehr über Tester und Feedback jeder Art freuen!
Schließlich darf ich noch unterstreichen, was Sven bereits in seinem Artikel dargestellt hat: Serverseitige Lösungen wie Adaptive Images oder squeezr sind keine langfristigen Lösungen für das Problem responsiver / adaptiver Bilder, auch wenn sie für den Moment einfach und effektiv funktionieren mögen. Es sollten vielmehr die diversen Initiativen zur Entwicklung geeigneter Standards unterstützt werden, z.b. die „Responsive Images Community Group“ (http://responsiveimages.org) oder ganz aktuell die entsprechende Appelle an die Browserhersteller (https://bugzilla.mozilla.org/show_bug.cgi?id=870022 oder https://code.google.com/p/chromium/issues/detail?id=233751).
Test
Test 2