scrset
srcset ist eine Liste von unterschiedlich hoch auflösenden Versionen eines Bildes, gefolgt von der Breite (Auflösung) des jeweiligen Bildes. Die Breite der Bilder ist mit "w" für width beziffert.
<img src="img1.png" srcset="img2.png 100w, img3.png 500w, img4.png 1000w" …">
Für Browser, die srcset nicht unterstützen (IE11 und älter), ist das altgediente src-Attribut ausschlaggebend.
<img loading="lazy" src="kitties-980.webp" width="980" height="604" alt="HTML img srcset – 4 Versionen, Auflösungen" srcset="kitties-420.webp 420w, kitties-980.webp 980w, kitties-1680.webp 1680w, kitties-2400.webp 2400w" sizes="(max-width: 900px) 90vw, (max-width:1100px) 70vw, 40vw">
- Wird das Bild im Porträt-Modus des Handys geladen, lädt der Browser die höhere Auflösung im Landscape-Modus nach, wenn das Handy gedreht wird.
- Beim Öffnen der Seite im Landscape-Modus und Drehen ins Hochformat: Die größere Version darf bleiben.
sizes - Bildgrößen fürs Layout
Ohne die Angabe von sizes, nur mit srcset, würden der Browser ein Bild entsprechend der Fensterbreite aussuchen und die Anzeigegröße im Layout außer Acht lassen. Wenn das Bild nicht gerade zur fensterfüllenden Slideshow gehört, würden hier zu große Bilddateien ausgeliefert. Die mittlere Spalte dieses Layouts ist auf großen Monitoren nur rund 900px breit.
Selbst auf einem großen Monitor mit einer Auflösung von 2048 x 1152 oder mehr hat das Bild im Layout höchstens eine Breite von +/- 900px. Darum gibt der Validator einem img-Tag mit srcset, aber ohne sizes keinen Segen: Wo Bilder mit srcset angeboten werden, teilt das Attribut sizes dem Browser das tatsächliche Platzangebot mit.
Für die ungefähr passgenaue Auslieferung der Bilddatei kommt also das Attribut sizes ins Spiel. sizes listet Bedingungen, ähnlich wie Media Queries.
sizes="(max-width: 900px) 90vw, /** Viewport max. 900px, nimm ein Bild mit ~90% der Viewport-Breite (vw) **/ (max-width:1100px) 70vw, /** Viewport max. 1100px, nimm ein Bild mit ~70% der Viewport-Breite (vw) **/ 40vw"> /** für alle übrigen Fälle nimm ein Bild mit 40% der Viewport-Breite (vw) **/
Der Browser wird die erste passende Bedingung heranziehen.
srcset und sizes
sizes ist die Vorgabe, in welcher Situation welche Bildgröße eingesetzt wird. Das passiert anhand einer Media Query und jeweiligen Breite des Bildes. Wenn die Seite auf einem großen Monitor eine Sidebar setzt, muss das Bild nicht für die volle Breite des Viewports reichen, sondern nur für die jeweilige Breite des umfassenden Blocks.
<img loading="lazy" width="980" height="604" alt="srcset und sizes für große Monitore" style="width:100%" src="img/vasen-980.webp" srcset="img/vasen-420.webp 420w, img/vasen-980.webp 980w, img/vasen-1680.webp 1680w, img/vasen-2400.webp 2400w" sizes="(max-width: 900px) 90vw, (max-width:1100px) 70vw, 60vw">
Wir haben also weiterhin in srcset die Liste mit den verschiedenen Auflösungen des Bildes. sizes legt den Raum fest, den das Bild innerhalb des Layouts einnimmt.
Mit sizes und srcset bestimmt also nicht mehr die Größe des Viewports allein über die Wahl des Bildes.
Die Media Querys verlangen nach Bildern, für die keine entsprechende Bildauflösung vorhanden ist. Kein Problem – das überlassen wir dem Browser, der die beste Bildgröße aus den verfügbaren Vorgaben wählt. Das macht die Kombination aus srcset und sizes so flexibel.
Auch wenn Handy und Tablet hochkant nach außen 393px bzw 744px Breite zeigen, ist ihre physikalische Auflösung deutlich höher: Sie haben Retina-Monitore. Wie schon zu Beginn des Beitrags erwähnt: Bei Retina-Monitoren greift der Browser u.U. automatisch nach der zwei- oder dreifachen Auflösung.
Die Auflösung der Retina-Monitore
Die Auflösung ist das Merkmal für die Schärfe und Farbbrillanz des Bildes und ist ein Qualitätsfaktor von Monitoren als auch von Bildern (so wie beim Drucker).
Hoch auflösende Bilder mit ihren langen Ladezeiten sind eine Belastung für responsive Webseiten auf mobilen Geräten. Auf der einen Seite wollen wir eine hohe Qualität für große Monitore und Retina-Displays, auf der anderen Seite wollen wir Mobiltelefone und Tabletts nicht mit den großen Bildern erschlagen: Bandbreite bleibt kostbar. loading="lazy" ist hier immer angebracht, damit Bilder gar nicht erst geladen werden, wenn der Benutzer nicht bis zum Standort der Bilder scrollt.
Die Auflösung des Monitors (PPI – Pixel pro Inch) wird in Pixeln für die Breite und die Höhe angegeben. Herkömmliche Desktop-Monitore stellen ein Bild i.d.R. mit 72, 96 oder 120 Pixeln pro Inch dar. Retina-Displays erreichen extreme Auflösungen von rund 300 bis 400 Pixeln pro Inch. So kommt es, dass große Monitore eine geringere Auflösung als kleine Monitore haben können.
Bei Fotos ist mit Auflösung die Zahl der Pixel in der Breite und Höhe gemeint. Zusätzlich haben Fotos auch eine Druck-Auflösung (meist 300 DPI – Dots per Inch), die aber für den Monitor irrelevant ist.
Anstelle der Breite in der srcset-Liste kann die Pixeldichte eingesetzt werden – 1x für eine einfache Auflösung, 2x für Monitore mit 200 ppi (Pixeln per Inch), 3x … usw.. Wenn die Auflösung bzw. Pixeldichte mit 1x, 2x, notiert ist, wird kein sizes-Attribut gesetzt.
<img src="celtic-980.webp" width="980" height="507" alt="celtic-980" srcset="celtic-3232.webp 4x, celtic-1616.webp 3x, celtic-1260.webp 2x, celtic-1616.webp 1x"
Kein sizes-Attribut: Der Browser erkennt die Größe und ppi-Auflösung des Viewports, die jeweils eingesetzt Bildgröße unterliegt dem Autor der Webseite. Bei einem srcset-Attribut mit Breitenangabe der einzelnen Bildversionen bestimmt der Autor durch das sizes-Attribut für welchen Viewport welche Bildgröße angesetzt wird und hat eine bessere Kontrolle über das Ausspielen von Fotos.
Bei den meisten Fotos wollen wir nicht die 3-fache oder 4-fache Auflösung, denn das wäre einfach Overkill. Handys haben so hohe Auflösungen, um Video in HD-Qualität zu liefern. Für Produktbilder, bei denen Farbtreue und Details eine große Rolle spielen, ist u.U. die 2-fache Auflösung angebracht. Für Grafiken reicht meistens die einfache Auflösung (1x). Gehen wir davon aus, dass die Seiten auch unterwegs besucht werden, wären so hohe Auflösungen kontraproduktiv.
Der Browser nimmt was passt
Hier stehen also zwei Bildgrößen zur Verfügung, die je nach Auflösung des Monitors geladen und angezeigt werden. Der Browser entdeckt die Auflösung / Pixeldichte des Monitors und entscheidet, welches Bild er einsetzt.
1x bzw. 2x steht für Device Pixel Ratio – das Verhältnis [Anzahl der Pixel in der Breite] zu [Breite in Zoll].
- 1x steht für herkömmliche Monitore, die mit 72 bis 100 Pixeln pro Zoll auflösen,
- 2x steht für hochauflösende Monitore, die mit 200 Pixeln und höher pro Zoll auflösen – sogen. »Retina«-Monitore. Heute sitzen wir vor mobilen Geräten, die 500 bis 800 Pixel per Inch (PPI) auflösen.
Der Browser wird das 2x-Bild automatisch um den Faktor 2 verkleinert anzeigen, damit es denselben Raum ausfüllt wie das das Bild mit der 1x-Auflösung. Dieses Verhalten ähnelt der Angabe der DPI bei Bildern für den Druck. Der Zeitschriften- und Buchdruck arbeitet i.d.R. mit 300 dpi, während Bilder auf dem Desktop-Monitor mit 72 - 120 dpi angezeigt werden.
Monitor-Auflösung und Pixel-Auflösung
Allerdings: Die Angabe der Bildschirmauflösung als Kriterium führt dazu, dass nicht nur auf großen Retina-Monitoren wie dem MacBook Pro, sondern auch auf kleinen Monitoren – z.B. Handy – die 2x- bis 4x-Auflösung angezeigt wird. Hier ist also eine weitere Differenzierung nötig.
Das Bild mit der zweifachen Auflösung soll nur geladen werden, wenn der Platz im Layout verfügbar ist.
Die Kondition für den Einsatz verschiedener Bildgrößen drei Parameter einbeziehen:
- Bildgröße relativ zum Viewport (z.B. 33.3vw )
- Breite des Viewports z.B. 640px oder 40em
- Auflösung des Monitors 1x, 2x, …
Welche Größen in den Browsern tatsächlich geladen werden, kann mit den Android- / iOS-Simulatoren getestet werden. Zwar bieten sowohl Firefox als auch Chrome in den Inspektoren auch Tests mit Auflösungen für Mobiltelefone und Tabletts an, aber sie verwenden bei Tests mit dem Desktop-Monitor auch die Auflösung des Desktop-Monitors.
srcset = [media query] [length], [media query] [length], … sizes = "(min-width: 42.5em) 50vw,100vw"
1 2 3 + + + | | | v v v <img sizes="(max-width:720px) 100vw, (max-width: 1260px) 70vw, calc(50vw - 100px)" srcset="picture-flowers-320.jpg 320w, /html/img/picture-flowers-640.jpg 640w, /html/img/picture-flowers-720.jpg 720w, /html/img/picture-flowers-960.jpg 960w, /html/img/picture-flowers-1120.jpg 1600w" src="/html/img/picture-flowers-640.jpg" alt="HTML img: srcset und sizes">
- (max-width:720px) 100vw – bis zu einer Breite des Viewports von 720px wird das Bild in voller Breite angezeigt
- (max-width:1260px) 70vw – bei einer Breite des Viewports bis zu 1260px tritt ein Spaltenlayout in Kraft und das Bild liegt in einer Spalte von 70% der Breite des Viewports.
- calc(50vw - 100px) – bei noch größeren Viewports liegt das Bild in einer Spalte von 50% der Viewport-Breite (minus 100px Abstand zwischen den Spalten)
Natürlich müssen nicht immer so viele Bildgrößen wie in diesem Beispiel angelegt werden – dahinter sollte auch die Frage stehen, wie groß die Ersparnis zwischen den einzelnen Stufen tatsächlich ist. Hier haben wir nur eine Demo.
Wenn anstelle eines Bildes mit gleichem Ausschnitt und gleichen Seitenverhältnissen Bilder mit unterschiedlichen Ausschnitten oder in unterschiedlichen Formaten gezeigt werden sollen – z.B. ein quadratischer Ausschnitt für Handys im Hochformat –, dann ist ein HTML picture-Element u.U. die bessere Wahl als img mit sizes und srcset.
Browser-Support für srcset
Alle modernen Browser außer IE bis einschließlich IE11.