Bilder optimal für performante Websites aufbereiten
Bilder sind ein zentraler Bestandteil jeder Webseite und entscheiden mit darüber, ob ein Webauftritt als benutzerfreundlich und professionell wahrgenommen wird – oder eben nicht. Um sicherzustellen, dass deine Bilder schnell laden und auf allen Geräten gut aussehen, solltest du einige Best Practices befolgen.
In diesem Artikel erfährst du, was sich hinter dem AVIF-Dateiformat verbirgt, wie du das <picture>
-Element mit srcset
und sizes
richtig nutzt, wie du dir die Arbeit in Visual Studio Code erleichtern kannst, oder mit einem Batch-Skript die Erstellung optimierter Bildversionen vereinfachst.
Dateiformate für Webauftritte
Die Wahl des richtigen Dateiformats ist entscheidend für die Performance deiner Webseite. Hier sind die gängigsten Formate und ihre Vor- bzw. Nachteile:
- AVIF: Ein modernes Format, das die besten Komprimierungsraten bei hoher Bildqualität bietet. AVIF unterstützt sowohl verlustbehaftete als auch verlustfreie Komprimierung und ist ideal für Fotos und Grafiken. Es unterstützt kein progressives Rendering, sodass Dateien vollständig heruntergeladen werden müssen, bevor sie angezeigt werden können, was aber in der Praxis kaum auffällt. Die Browserunterstützung liegt zur Zeit (im Februar 2025) bei ca. 95 %.
- WebP: Ein weiteres modernes Format. WebP bietet in der Regel bessere Komprimierungsraten als JPEG und PNG. Die Browserunterstützung ist mit ca. 97 % mittlerweile sehr gut.
- JPEG, PNG und Gif: Diese Dateiformate sind nur noch in Ausnahmefällen sinnvoll. JPEG und PNG bieten im Vergleich zu AVIF und WebP eine eher mäßige Komprimierung bei akzeptabler Qualität, sind aber inzwischen nicht mehr die ideale Lösung für Webauftritte. JPEG wird von allen Webbrowsern unterstützt und du kannst es gegebenenfalls noch als Fallback für veraltete Browser nutzen. Im Gegensatz zu den anderen hier vorgestellten Dateiformaten unterstützt JPEG keine Transparenz.
Bei PNG hast du die Möglichkeit, mit transparenten Hintergründen und verlustfreier Komprimierung zu arbeiten. Und wenn du eine animierte Pixelgrafik zeigen möchtest, um etwas 90er-Jahre Charme in deinen Webauftritt zu bringen, könntest du mit Gif-Dateien arbeiten 😉 Gifs haben mit maximal 256 Farben im Vergleich zur Abbildungsqualität allerdings eine sehr hohe Dateigröße.
JPEG XL hat eine ähnlich gute Kompression wie AVIF, wird aber zurzeit nur von 14 % aller Webbrowser unterstützt. - SVG: Für Vektorgrafiken wie Logos und Icons. SVG-Dateien sind skalierbar und behalten ihre Qualität bei jeder Größe. Mehr zu diesem Dateiformat findest du in meinem Artikel unter https://web-einfach-machen.de/Blog/edv/svg-vektorgrafik-im-webbrowser/.
Weitere detaillierte Informationen zu den Dateiformaten findest du unter https://developer.mozilla.org/de/docs/Web/Media/Guides/Formats/Image_types.
AVIF-Konvertierung mit avifenc
In diesem Artikel geht es vor allem um das zukunftsweisende AVIF Format.
Es wird zwar von einem kleinen Teil der Webbrowser nicht unterstützt, aber das ist kein Problem. Mithilfe des Picture-Elements hast du für solche Uralt-Browser eine ausgezeichnete Fallback-Lösung zur Verfügung. Mehr dazu weiter unten in diesem Artikel.
Um die erstaunliche Qualität der AVIF-Komprimierung einschätzen zu können, schaust du dir am besten die verschiedenen Beispielbilder auf meiner Demo-Seite unter https://web-einfach-machen.de/Kursmaterialien/Kurs_Frontend-komplett/Vorarbeiten/Vergleich-Kompression-Qualitaet.html an. Hier siehst du verschiedene Komprimierungs-Varianten im direkten Vergleich.
Die einzelnen Bilder habe ich größtenteils mit dem Programm avifenc
erstellt, das ist ein sogenanntes Kommandozeilen-Programm. Um damit zu arbeiten, muss man in seinem Betriebssystem ein Terminal öffnen. Zum Arbeiten mit dem Terminal auf deinem Betriebssystem habe ich dir in den Literaturhinweisen ein paar Tutorials verlinkt. Du kannst AVIF-Dateien auch mit Programmen wie Gimp oder Adobe Photoshop (im Februar 2025 nur Windows und mit kostenpflichtigen PlugIn) abspeichern. Du hast aber im Terminal mehr Möglichkeiten für das Feintuning, deswegen erkläre ich die einzelnen Optionen bei der AVIF-Komprimierung anhand des Kommandozeilenprogramms „avifenc“. Lass uns also einen beispielhaften Befehl näher betrachten: Zunächst ein Beispiel für eine Konvertierung mit ausgewogener Balance zwischen Kompression und Qualität: avifenc -j all -s 3 --min 0 --max 63 -a tune=ssim --ignore-icc
input.jpg output.avif
Hier wird zunächst mit avifenc
der Encoder (das Programm) avifenc im Terminal aufgerufen. Danach folgen verschiedene Parameter.
Als erster Parameter steht in diesem Beispiel mit -j all
die Anzahl der Jobs (Threads), hier wird die CPU aufgefordert, alle vorhandenen Kerne für die einzelnen Threads des Prozesses zu nutzen, was die Verarbeitungsgeschwindigkeit erhöht.
Der Parameter -s 3
beeinflusst die Geschwindigkeit der Kodierung. Die Skala reicht hier von 0 (am langsamsten) bis 10 (am schnellsten). Wenn du einen niedrigen Wert festlegst, dauert das Erstellen der komprimierten Datei ein wenig länger, dafür wirst du mit einer etwas kleineren Dateigröße belohnt.
Die Parameter --min 0 --max 63
beziehen sich auf die Quantisierungsparameter (QP) für die Bildkompression.
„- -min 0“ setzt den minimalen Quantisierungswert auf 0, was der höchsten Qualität entspricht.
„- -max 63“ setzt den maximalen Quantisierungswert auf 63, was der niedrigsten Qualität entspricht. Diese Einstellung erlaubt dem Encoder, für jeden Block im Bild den optimalen QP-Wert zwischen 0 und 63 zu wählen. Dies ermöglicht eine effizientere Kodierung und bessere psychovisuelle Qualität, da der Encoder die Kompression an die Anforderungen verschiedener Bildbereiche flexibel anpassen kann. Im Gegensatz dazu würde eine Einstellung wie „–min 20 –max 20“ den Encoder zwingen, für jeden Block denselben QP-Wert zu verwenden, was in der Regel zu einem weniger optimalen Ergebnis führt.
Weitere Parameter sind -a tune=ssim
: „-a tune=ssim“ (Structural Similarity Index Measure) sorgt für eine größere visuelle Ähnlichkeit zwischen dem Original und dem komprimierten Bild.
Diese Einstellung kann die Dateigröße leicht reduzieren.
Und „--ignore-icc
“ Dieser Parameter ignoriert eingebettete ICC-Farbprofile im Eingabebild.
Und am Ende des Befehls gibst du mit „input.jpg output.avif
“ die Ausgangsdatei und den Namen der komprimierten Ausgabe-Datei an.
Wenn du avifenc -h
im Terminal eingibst, bekommst du die Hilfe mit den kompletten Optionen des Encoders angezeigt. Hier habe ich auf meiner Demoseite beispielsweise film-grain-test=1
für die Kodierungen mit problematischen Verläufen genutzt.
Um mit mit dem Kommandozeilenprogramm avifenc zu arbeiten zu, musst du es auf deinem Betriebssystem erstmal installieren. Das geht unter Linux zum Beispiel mit apt. Und unter MacOS mit dem Paketmanager Homebrew (brew install joedrago/repo/avifenc
), der wiederum die Xcode Command Line Tools erfordert. Im Videotutorial „How to Install Homebrew on Mac“: https://www.youtube.com/watch?v=IWJKRmFLn-g findest du dazu eine Anleitung.
Arbeiten mit dem Terminal?
Das Abspeichern eines Bildes als AVIF-Datei lässt sich auch mit Programmen wie Gimp oder https://squoosh.app/ realisieren, aber mit den hier beschriebenen Techniken bist du flexibler, kannst mit Stapelverarbeitungen arbeiten und holst das Beste aus deinen Bildern raus. Tatsächlich ist das Arbeiten mit dem Terminal kein Hexenwerk und in einigen Situationen ein echter Rettungsanker.
Zum Arbeiten mit dem Terminal kann ich dir folgende Literatur empfehlen:
Beginners tutorial: https://ubuntu.com/tutorials/command-line-for-beginners#3-opening-a-terminal
Die 15 wichtigsten Linux-Befehle im Terminal: https://www.giga.de/extra/linux/specials/linux-befehle/
Die 20 wichtigsten Kommandos: https://www.heise.de/tipps-tricks/Linux-Befehle-Die-20-wichtigsten-Kommandos-3843388.html
Video – 20 Terminal Befehle in 6 Minuten: https://www.youtube.com/watch?v=J2SXhVzVJbM
Bilder für responsive Webseiten
Verwende in deinen Webprojekten keine Bilder mit unnötig hohen Auflösungen. Um Bilder responsiv in die Webseite einzubinden, kannst du mit den Attributen scrset
und sizes
arbeiten.
Srcset ist eine Liste von unterschiedlich aufgelösten Versionen deines Bildes mit der Angabe, für welche Breite das Bild geeignet ist.
Mit dem Attribut sizes legst du die Bedingungen fest, wie groß das Bild im Seiten-Layout dargestellt werden soll. Ohne die Angabe von sizes würde der Browser ein Bild immer auf der Grundlage der kompletten Fensterbreite raussuchen, auch wenn beispielsweise in einem zweispaltigen Layout das Bild nur 50 % des kompletten Viewport einnimmt. Der Viewport ist der sichtbare Teil des Browserfensters, also ohne Elemente wie Scrollbalken oder Adressleiste.
Du kannst den Einsatz von sizes gut anhand meines Beispiels unter der Adresse https://web-einfach-machen.de/Kursmaterialien/Kurs_Frontend-komplett/Vorarbeiten/srcset.html nachvollziehen.
In diesem Beispiel sollen Bilder auf größeren Monitoren (bei einer Viewportbreite ab 920 Pixel) zwei- beziehungsweise drei-spaltig angezeigt werden. Auf Smartphones unterhalb von 921 Pixel Viewportbreite hingegen sollen sie formatfüllend über die gesamte Breite des Browserfensters angezeigt werden.
Da ist zunächst ein Bild, was oben auf der Seite als Aufmacherbild auf Displays über 920 Pixel Auflösung eine Breite von 100% des Elternelementes hat.
Da drunter siehst du auf meiner Beispielseite ein zwei- bzw. drei-spaltiges Layout.
In allen Fällen soll jeweils eine Version des Bildes geladen werden, die nicht unnötig groß ist, aber eine ausreichende Auflösung hat, um zum einen in das Layout zu passen und zum anderen auch bei Bildschirmen mit einer höheren DPR (device-pixel-ratio) nicht unscharf aussieht.
Die Device Pixel Ratio eines Displays gibt an, wie viele Hardwarepixel des Displays zu einem logischen CSS Pixel zusammengefasst werden. So hat zum Beispiel das Retina Displays eines iPhone 16 Pro eine DPR von 3, was dazu führt, dass seine physische Bildschirmauflösung von 1320 x 2868 Pixeln in 440 × 956 CSS-Pixel resultiert.
Hier der dazugehörige HTML Code, um die Bilder responsiv einzubinden; zunächst das Aufmacherbild mit 50% Breite auf Ausgabegeräten über 920px Viewportbreite:
<img srcset="Bilder/dummy-400.webp 400w,
Bilder/dummy-800.webp 800w,
Bilder/dummy-1024.webp 1024w,
Bilder/dummy-1600.webp 1600w,
Bilder/dummy-2048.webp 2048w,
Bilder/dummy-3840.webp 3840w"
sizes="(max-width:920px) 100vw, 50vw"
src="Bilder/dummy-1024.webp" alt="Ein sehr schönes Bild" width="1024" height="512">
Mit dem Attribut srcset lege ich zunächst mehrere Bildquellen fest, aus denen der Browser je nach Bildschirmgröße und Auflösung das passende auswählt.
Mit dem Attribut sizes, sage ich dem Webbrowser durch die Angabe (max-width: 920px) 100vw
, dass das Bild bis zu einer Viewportbreite von 920 Pixel die komplette Breite des Viewports einnehmen soll. Denn auf Smartphones bevorzuge ich eine ein-spaltige Darstellung. Ab einer Größe von 921 Pixel hingegen ändert sich mein Seitenlayout auf zwei-spaltig und hier sorgt die Angabe von 50vw
dafür, dass das Bild nur noch 50 % der Viewportbreite benötigt und eine entsprechend kleinere Datei geladen werden kann.
Falls ein sehr veralteter Browser das Attribut srcset nicht kennen sollte, wird ein Fallback-Bild mithilfe der Angabe src="Bilder/dummy-1024.jpg"
angezeigt.
Und nun zu den drei Bildern, welche auf Smartphones bis 920 Pixeln vollformatig über die komplette Breite, auf Desktop-PC Monitoren hingegen in einem dreispaltigen Layout angezeigt werden sollen.
img srcset="Bilder/dummy-400.webp 400w,
Bilder/dummy-800.webp 800w,
Bilder/dummy-1024.webp 1024w,
Bilder/dummy-1600.webp 1600w,
Bilder/dummy-2048.webp 2048w,
Bilder/dummy-3840.webp 3840w"
sizes="(max-width:920px) 100vw, 33vw"
src="Bilder/dummy-1024.webp" alt="Ein sehr schönes Bild" width="1024" height="512">
Hier sorgt die Angabe von 33vw
ab einer Breite von 921 Pixeln dafür, dass die Bezugsbreite für das srcset nur noch ein Drittel der Viewportbreite betragen soll. Unterhalb von 921px wird 100vw als Bezugsgröße genommen, wobei die Annahme von 100vw ohnehin der Standard ist, falls keine andere Angabe gemacht wird.
Am besten schaust du dir das wie gesagt direkt an meinem Beispiel auf https://web-einfach-machen.de/Kursmaterialien/Kurs_Frontend-komplett/Vorarbeiten/srcset.html an und veränderst die Breite deines Browserfenster. Hier siehst du, welche Bilder bei welcher Fensterbreite vom Browser geladen werden. Hier wird auch automatisch die DPR des Displays in die Berechnung einbezogen.
Du hast übrigens in den Entwicklertools von Browsern wie Firefox oder Chrome auch die Möglichkeit, eine individuelle device-pixel-ratio zu simulieren. Wenn du die DPR auf zwei oder drei erhöhst, werden dir entsprechend höher aufgelöste Bilder angezeigt.
Das picture-Element
Eine einfache Möglichkeit, Bilder in Webseiten einzubinden, ist das img-Element. Wenn du Bilder aber responsiv für verschiedene Ausgabegeräte optimiert anzeigen willst, dann empfehle ich dir stattdessen das <picture>
-Element . Das <picture>
-Element ermöglicht es dir, nicht nur verschiedene Bildversionen für unterschiedliche Bildschirmgrößen und Auflösungen bereitzustellen, sondern auch das Bild im optimalen Dateiformat bereitzustellen.
Das Picture-Element kann mehrere source-Elemente enthalten, wobei der Webbrowser die erste source, also die erste Quelle, die er verarbeiten kann, anzeigt. Damit der Browser die optimale Datei finden kann, kannst du im Picture Element mit Media Queries und Attributen wie zum Beispiel sizes arbeiten.
Hier ist ein Beispiel, wie du das <picture>
-Element mit srcset
und sizes
verwenden kannst:
<picture>
<!-- AVIF -->
<source type="image/avif" srcset="
Bilder/dummy-400.avif 400w,
Bilder/dummy-800.avif 800w,
Bilder/dummy-1024.avif 1024w,
Bilder/dummy-1600.avif 1600w,
Bilder/dummy-2048.avif 2048w,
Bilder/dummy-3840.avif 3840w" sizes="(max-width:920px) 100vw, 50vw">
<!-- Webp -->
<source type="image/webp" srcset="
Bilder/dummy-400.webp 400w,
Bilder/dummy-800.webp 800w,
Bilder/dummy-1024.webp 1024w,
Bilder/dummy-1600.webp 1600w,
Bilder/dummy-2048.webp 2048w,
Bilder/dummy-3840.webp 3840w" sizes="(max-width:920px) 100vw, 50vw">
<!-- Fallback mit JPEG -->
<img src="Bilder/dummy-3840.jpg" alt="Ein sehr schönes Bild" width="3840" height="1920" loading="lazy" srcset="
Bilder/dummy-400.jpg 400w,
Bilder/dummy-800.jpg 800w,
Bilder/dummy-1024.jpg 1024w,
Bilder/dummy-1600.jpg 1600w,
Bilder/dummy-2048.jpg 2048w,
Bilder/dummy-3840.jpg 3840w" sizes="(max-width:920px) 100vw, 50vw">
</picture>
In diesem Beispiel passiert folgendes: Mit dem source-Element kannst du mehrere Bildquellen angeben, die der Browser je nach Bildschirmgröße und Auflösung auswählt. Die Dateiformate, die er nicht unterstützt, überspringt der Browser. Ein Safari 16.0 würde beispielsweise eine AVIF Datei nicht verarbeiten können und zu WebP springen. Auch die für die Anzeige benötigte Mindestbreite des Bildes kann der Browser anhand von srcset und sizes aus der Liste auswählen. Die erste Datei, deren Medienabfrage einen Treffer ergibt, wird im Webbrowser angezeigt.
Welche Datei hier vom Webbrowser genommen wird, ist also davon abhängig, ob er einen bestimmten Dateityp verarbeiten kann, in welcher Größe die Datei abgebildet wird und welche Device Pixel Ratio das Display besitzt.
Im picture-Element lassen sich übrigens auch Media-Abfragen wie beispielsweise orientation: landscape oder oder prefers-color-scheme: dark und ähnliche einsetzen, um die richtige Bildquelle zu wählen. Siehe den folgenden Code-Schnipsel von https://www.mediaevent.de/html/picture.html.
<picture>
<source media="(min-width: 300px) and (orientation:portrait) and (prefers-color-scheme: dark)" srcset="nacht-800.webp">
<source media="(min-width: 300px) and (orientation:landscape) and (prefers-color-scheme: dark)" srcset="nacht-1000.webp">
<source media="(min-width: 300px) and (orientation:portrait)" srcset="tag-800.webp">
<source media="(min-width: 300px) and (orientation:landscape)" srcset="tag-1000.webp">
<img loading="lazy" src="tag-1000.webp" width="1108" height="458" alt="tag-1000">
</picture>
Automatisierung in Visual Studio Code
Das manuelle Schreiben des Codes für das <picture>
-Element kann etwas mühsam sein, insbesondere wenn du viele Bilder auf deiner Website hast. Zum Glück kannst du dir die Arbeit in Visual Studio Code erleichtern, indem du Snippets und Erweiterungen verwendest.
Snippets in Visual Studio Code
Snippets sind vorgefertigte Codeblöcke, die du in VS Code schnell einfügen kannst. Und so erstellst du ein Snippet für das <picture>
-Element:
- Öffne in Visual Studio Code die Kommando-Palette mit
Strg+Shift+P
(Windows/Linux) oderCmd+Shift+P
(Mac). - Suche nach „Konfigurieren von Codeausschnitten“ oder „Configure User Snippets“ und wähle „New Snippets“ aus.
- Wähle ggf. die Sprache aus, für die du das Snippet erstellen möchtest (z.B. HTML).
- Füge den folgenden Code in die Snippet-Datei ein:
{
// Place your global snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field.
// picture-Elemente
"Bild (Vollständig über die gesamte Breite)": {
"prefix": "bildvoll", // Das Kürzel, um das Snippet auszulösen.
"body": [
"<picture>",
" <!-- AVIF -->",
" <source",
" type=\"image/avif\"",
" srcset=\"",
" ${1:Bild}-400.avif 400w,",
" ${1:Bild}-800.avif 800w,",
" ${1:Bild}-1024.avif 1024w,",
" ${1:Bild}-1600.avif 1600w,",
" ${1:Bild}-2048.avif 2048w,",
" ${1:Bild}-3840.avif 3840w\"",
" sizes=\"100vw\">",
"",
" <!-- WebP -->",
" <source",
" type=\"image/webp\"",
" srcset=\"",
" ${1:Bild}-400.webp 400w,",
" ${1:Bild}-800.webp 800w,",
" ${1:Bild}-1024.webp 1024w,",
" ${1:Bild}-1600.webp 1600w,",
" ${1:Bild}-2048.webp 2048w,",
" ${1:Bild}-3840.webp 3840w\"",
" sizes=\"100vw\">",
"",
" <!-- Fallback JPG mit fetchpriority -->",
" <img",
" src=\"${1:Bild}-3840.jpg\"",
" srcset=\"",
" ${1:Bild}-400.jpg 400w,",
" ${1:Bild}-800.jpg 800w,",
" ${1:Bild}-1024.jpg 1024w,",
" ${1:Bild}-1600.jpg 1600w,",
" ${1:Bild}-2048.jpg 2048w,",
" ${1:Bild}-3840.jpg 3840w\"",
" sizes=\"100vw\"",
" alt=\"${2:Bildbeschreibung}\"",
" fetchpriority=\"high\"",
" width=\"20\"",
" height=\"20\">",
" <!-- Preload bei Aufmacherbildern above the fold manuell in den head setzen. Ggf. für Bilder, die nicht als Aufmacherbild dienen, ein lazy-loading hinzufügen und fetchpriority entfernen. width und height per Emmet-sizes anpassen. -->",
"</picture>"
],
"description": "Fügt ein Bild ein, das immer die gesamte Breite der Seite einnimmt"
},
"Bild (Responsiv, 2 Breakpoints, Lazy Loading)": {
"prefix": "bild2bp", // Das Kürzel, mit dem du das Snippet auslösen kannst
"body": [
"<picture>",
" <!-- AVIF -->",
" <source",
" type=\"image/avif\"",
" srcset=\"",
" ${1:Bild}-400.avif 400w,",
" ${1:Bild}-800.avif 800w,",
" ${1:Bild}-1024.avif 1024w,",
" ${1:Bild}-1600.avif 1600w,",
" ${1:Bild}-2048.avif 2048w,",
" ${1:Bild}-3840.avif 3840w\"",
" sizes=\"(max-width: 920px) 100vw, 50vw\">",
"",
" <!-- WebP -->",
" <source",
" type=\"image/webp\"",
" srcset=\"",
" ${1:Bild}-400.webp 400w,",
" ${1:Bild}-800.webp 800w,",
" ${1:Bild}-1024.webp 1024w,",
" ${1:Bild}-1600.webp 1600w,",
" ${1:Bild}-2048.webp 2048w,",
" ${1:Bild}-3840.webp 3840w\"",
" sizes=\"(max-width: 920px) 100vw, 50vw\">",
"",
" <!-- Fallback JPG mit Lazy Loading -->",
" <img",
" src=\"${1:Bild}-2048.jpg\"",
" srcset=\"",
" ${1:Bild}-400.jpg 400w,",
" ${1:Bild}-800.jpg 800w,",
" ${1:Bild}-1024.jpg 1024w,",
" ${1:Bild}-1600.jpg 1600w,",
" ${1:Bild}-2048.jpg 2048w,",
" ${1:Bild}-3840.jpg 3840w\"",
" sizes=\"(max-width: 920px) 100vw, 50vw\"",
" alt=\"${2:Bildbeschreibung}\"",
" loading=\"lazy\"",
" width=\"20\"",
" height=\"20\">",
" <!-- Ggf. große srcsets bei gering aufgelösten Bildern löschen und „Bild-original.jpg“ für Fallback nutzen; width und height per Emmet-sizes anpassen. -->",
"</picture>"
],
"description": "Fügt ein responsives Bild mit 2 Breakpoints und Lazy Loading ein"
},
"Bild (Responsiv, 3 Breakpoints, Lazy Loading)": {
"prefix": "bild3bp", // Das Kürzel, mit dem du das Snippet auslösen kannst
"body": [
"<picture>",
" <!-- AVIF -->",
" <source",
" type=\"image/avif\"",
" srcset=\"",
" ${1:Bild}-400.avif 400w,",
" ${1:Bild}-800.avif 800w,",
" ${1:Bild}-1024.avif 1024w,",
" ${1:Bild}-1600.avif 1600w,",
" ${1:Bild}-2048.avif 2048w,",
" ${1:Bild}-3840.avif 3840w\"",
" sizes=\"(max-width: 920px) 100vw, (max-width: 1600px) 50vw, 33.33vw\">",
"",
" <!-- WebP -->",
" <source",
" type=\"image/webp\"",
" srcset=\"",
" ${1:Bild}-400.webp 400w,",
" ${1:Bild}-800.webp 800w,",
" ${1:Bild}-1024.webp 1024w,",
" ${1:Bild}-1600.webp 1600w,",
" ${1:Bild}-2048.webp 2048w,",
" ${1:Bild}-3840.webp 3840w\"",
" sizes=\"(max-width: 920px) 100vw, (max-width: 1600px) 50vw, 33.33vw\">",
"",
" <!-- Fallback JPG mit Lazy Loading -->",
" <img",
" src=\"${1:Bild}-2048.jpg\"",
" srcset=\"",
" ${1:Bild}-400.jpg 400w,",
" ${1:Bild}-800.jpg 800w,",
" ${1:Bild}-1024.jpg 1024w,",
" ${1:Bild}-1600.jpg 1600w,",
" ${1:Bild}-2048.jpg 2048w,",
" ${1:Bild}-3840.jpg 3840w\"",
" sizes=\"(max-width: 920px) 100vw, (max-width: 1600px) 50vw, 33.33vw\"",
" alt=\"${2:Bildbeschreibung}\"",
" loading=\"lazy\"",
" width=\"20\"",
" height=\"20\">",
" <!-- Ggf. große srcsets bei gering aufgelösten Bildern löschen und „Bild-original.jpg“ für Fallback nutzen; width und height per Emmet-sizes anpassen. -->",
"</picture>"
],
"description": "Fügt ein responsives Bild mit 3 Breakpoints und Lazy Loading ein"
}
}
- Speichere die Datei.
Jetzt kannst du das Snippet verwenden, indem du ein Prefix wie z.B. „bild2bp“ eingibst und mit Tab die Autovervollständigung nutzt. Danach musst du nur noch die Platzhalter, also Dateiname und Alt-Text sowie height- und width-Attribute des Bildes manuell anpassen. Aber das geht bei dieser Arbeitsweise sehr zügig, die Platzhalter für die Dateinamen sind bereits alle ausgewählt.
Die Attribute height und width
In meinen Beispielen gebe ich für die Bilder übrigens immer die Attribute width und height an. Durch die Information zum Seitenverhältnis von Höhe zu Breite ermöglichst du es Webbrowsern, den Platz für das Bild bereits beim Seitenaufbau zu reservieren. Dadurch kann der Browser das Layout bereits rendern, bevor das Bild geladen ist und vermeidet ein Layout-shift. So bleibt das Layout stabil, auch wenn das Bild noch nicht geladen ist.
Auch hier ist VS Code hilfreich.
- Platziere den Cursor innerhalb des img-Tags.
- Öffne die Befehlspalette (unter Mac mit Cmd + Shift + p, bzw. unter Linux/Windows: Ctrl + Shift + p).
- Tippe in die Befehlspalette: „Emmet: Update Image Size“ (oder einfach nur „size“).
- Emmet ermittelt automatisch die Breite und Höhe des Bildes und schreibt sie in das img-Tag.
Bilderstellung mit einem Batch-Skript automatisieren
Um mit dem <picture>
-Element zu arbeiten, benötigst du viele unterschiedliche Versionen eines Bildes in diversen Auflösungen und Dateiformaten. Mit einem Batch-Skript im Terminal kannst du die Erstellung dieser Bilder automatisieren. Hier ist ein Beispiel, wie du dir die Arbeit mit ImageMagick oder avifenc erleichtern kannst. Dieses Skript erstellt automatisch verschiedene Versionen des Originalbildes in den Formaten AVIF, WebP und JPEG.
Das Skript benötigt Kommandozeilenprogramme wie imageMagick (zum Skalieren und Konvertieren von Bildern), cwebp (WebP-Konvertierung) oder avifenc (AVIF-Konvertierung – aus libavif).
Wenn du diese Programme auf deinem Rechner zur Verfügung hast, kannst du die Stapelverarbeitung starten:
- Erstelle ein Batch-Skript:
Erstelle eine Text-Datei (zum Beispiel mit dem Namen „Dateiformat-batch.sh“) und füge den folgenden Code ein:
#!/bin/bash
# Ein Skript zur Größen- und Dateiformat-Stapelverarbeitung von Bilddateien.
# Quell- und Zielverzeichnis definieren
SOURCE_DIR="./input_bilder" # Hier den Ordner mit den Originalbildern anpassen
OUTPUT_DIR="./output_bilder" # Zielverzeichnis für die konvertierten Bilder
# Falls das Ausgabe-Verzeichnis nicht existiert, erstelle es
mkdir -p "$OUTPUT_DIR"
# Definiere die gewünschten Breiten
SIZES=(400 800 1024 1600 2048 3840)
# Durchlaufe alle Bilder im Quellordner
for file in "$SOURCE_DIR"/*.{jpg,jpeg,png,webp,avif}; do
# Prüfe, ob die Datei existiert (damit keine Fehler auftreten)
[ -e "$file" ] || continue
# Extrahiere den Dateinamen und die ursprüngliche Breite
filename=$(basename "$file")
width=$(identify -format "%w" "$file")
# Originalgröße in hoher Qualität speichern
output_name="${filename%.*}-original"
# Original als JPEG (Qualität 90)
convert "$file" -quality 90 "$OUTPUT_DIR/${output_name}.jpg"
# Original als WebP (Qualität 90)
cwebp -q 90 "$file" -o "$OUTPUT_DIR/${output_name}.webp"
# Original als AVIF
avifenc -j all -s 4 --min 0 --max 63 -a cq-level=0 -a tune=ssim "$file" "$OUTPUT_DIR/${output_name}.avif"
# Zu kleine Bilder nicht künstlich hochskalieren. Falls das Original-Bild kleiner als 1025px ist, speichere es nur mit 400px, 800px und 1024px.
if [ "$width" -lt 1025 ]; then
selected_sizes=(400 800 1024)
else
selected_sizes=("${SIZES[@]}") # Nutze alle Größen
fi
# Erstelle für jede definierte Größe eine Version
for size in "${selected_sizes[@]}"; do
output_name="${filename%.*}-${size}"
# Verlustfreies PNG
convert "$file" -resize "${size}x" -define png:compression-level=9 -quality 100 "$OUTPUT_DIR/${output_name}.png"
# Erstelle verkleinertes JPEG (Qualität 80)
convert "$file" -resize "${size}x" -quality 80 "$OUTPUT_DIR/${output_name}.jpg"
# Erstelle WebP (Qualität 85)
cwebp -q 85 "$OUTPUT_DIR/${output_name}.png" -o "$OUTPUT_DIR/${output_name}.webp"
# Erstelle AVIF (ausgewogene Qualität)
avifenc -j all -s 4 -a cq-level=20 -a end-usage=q "$OUTPUT_DIR/${output_name}.png" "$OUTPUT_DIR/${output_name}.avif"
done
done
echo "Bildverarbeitung abgeschlossen!"
Stapelverarbeitung starten:
- Mache das Skript ausführbar:
chmod +x Dateiformat-batch.sh
- Führe das Skript im Terminal deines Betriebssystems aus mit:
./Dateiformat-batch.sh
Anpassungsmöglichkeiten
In dem oben stehenden Skript kannst du unter anderem den Pfad zum Quellordner ändern: Setze die Angabe SOURCE_DIR=“./Bilder“ auf deinen gewünschten Ordner.
Du kannst andere Qualitätsstufen wählen: Ändere die -quality Werte bei convert, cwebp oder avifenc.
Oder weitere Bildgrößen erstellen: Füge einfach weitere Werte zu SIZES=(400 800 … ) hinzu.
Lazy Loading
Neben den bislang besprochenen Techniken gibt es noch weitere Möglichkeiten, die Geschwindigkeit und Usability deiner Website zu verbessern. Lazy Loading beispielsweise ist eine Technik, bei der Bilder erst geladen werden, wenn sie im sichtbaren Bereich des Browsers erscheinen. Dies verbessert die Ladezeiten erheblich, da nicht alle Bilder sofort beim Laden der Seite heruntergeladen werden müssen. Um Lazy Loading zu aktivieren, füge einfach das loading="lazy"
-Attribut zu deinem <img>
-Tag hinzu:
<!-- WebP-Format -->
<source type="image/webp" srcset="Bilder/dummy-400.webp 400w,
Bilder/dummy-770.webp 770w,
Bilder/dummy-1440.webp 1440w,
Bilder/dummy-2880.webp 2880w" sizes="(max-width: 768px) 100vw, 50vw">
<!-- Fallback für ältere Browser (JPEG) -->
<img src="Bilder/dummy-2880.jpg" srcset="Bilder/dummy-400.jpg 400w,
Bilder/dummy-770.jpg 770w,
Bilder/dummy-1440.jpg 1440w,
Bilder/dummy-2880.jpg 2880w" sizes="(max-width: 768px) 100vw, 50vw" width="2880" height="2880" alt="Alternativtext" loading="lazy">
</picture>
Alternative CDN
Wenn du das Erstellen der Bildvarianten nicht selber vornehmen möchtest, könntest du auch Services wie Image Kit unter https://imagekit.io/ oder Cloudinary unter https://cloudinary.com/ nutzen. Hier kannst du ein hoch aufgelöstes Bild hochladen und anschließend werden dir unterschiedliche Varianten in verschiedenen Auflösung und Dateiformaten automatisch generiert. Das Hosten der Bilder auf solchen CDNs (Content Delivery Networks) kann allerdings Geschwindigkeitseinbußen nach sich ziehen.
Weitere Performance-Optimierungen
Mit Preloading und FetchPriority kannst du Resourcen bevorzugt laden, die beispielsweise im Kopfbereich der Seite „above the fold“ angezeigt werden; siehe https://developer.mozilla.org/de/docs/Web/API/HTMLImageElement/fetchPriority und https://developer.mozilla.org/de/docs/Web/HTML/Attributes/rel/preload.
Eine weitere Technik wäre decoding="async"
: Standardmäßig wird ein Bild im HTML-Element synchron dekodiert. Das bedeutet, dass der Browser die Bilddaten dekodiert, bevor er mit der Anzeige der Seite fortfährt. Wenn du jedoch decoding=“async“ verwendest, wird das Bild asynchron dekodiert. Das bedeutet, dass der Browser die Bilddaten in einem separaten Thread dekodiert, ohne den Hauptthread der Seite zu blockieren. So können andere Aufgaben wie das Rendern der restlichen Seite parallel ablaufen.
Wenn du viele oder große Bilder auf deiner Seite hast, kann das asynchrone Dekodieren helfen, die Ladezeiten zu verkürzen und die Gesamtleistung zu verbessern.
Allerdings laden moderne Webbrowser Bilder bereits intelligent, so dass diese Optimierungen in der Regel nur einen geringen Effekt haben.
Fazit
Durch die Verwendung der richtigen Dateiformate, des <picture>
-Elements mit srcset
und sizes
, Lazy Loading, Automatisierungen in Visual Studio Code und Batch-Skripte zur Bilderstellung kannst du sicherstellen, dass deine Bilder schnell laden und auf allen Ausgabegeräten gut aussehen.
Ich gebe zu, dass es ein bisschen aufwendiger ist, ein Bild über das picture-Element in eine Webseite einzubinden als nur über das img-Element, aber du wirst hier mit optimierten Ladezeiten, verbesserter Abbildungsqualität auch auf Bildschirmen mit hoher Auflösung und einem benutzerfreundlichen Webauftritt belohnt. Und natürlich trägt die Verbesserung der Ladegeschwindigkeit auch dazu bei, deinen Webauftritt SEO-optimiert, also suchmaschinenfreundlicher zu gestalten.
Literaturhinweise
Meine Youtubetutorials zum Thema „Bilder richtig in Webseiten einbetten“ findest du unter https://www.youtube.com/watch?v=1-vKgWLvNO0
und zu AVIF-Komprimierung: https://www.youtube.com/watch?v=O9bifhT8a-4
Quellcode meiner Beispieldatei aus dem Video: https://web-einfach-machen.de/Kursmaterialien/Kurs_Frontend-komplett/Vorarbeiten/picture-element.html
Bildergalerie mit AVIF-komprimierten Bildern im Vergleich: https://web-einfach-machen.de/Kursmaterialien/Kurs_Frontend-komplett/Vorarbeiten/Vergleich-Kompression-Qualitaet.html
Gute Artikel zum Thema picture-Element: https://www.mediaevent.de/html/picture.html,
https://webdesign.tutsplus.com/quick-tip-how-to-use-html5-picture-for-responsive-images–cms-21015t, https://developer.mozilla.org/de/docs/Web/HTML/Element/picture
Blog von Kyle (WDS): https://blog.webdevsimplified.com/2023-05/responsive-images/
Batch-processing in GIMP: https://www.youtube.com/watch?v=lAQtItwKKvo
Batch in Photoshop: https://www.youtube.com/watch?v=JcXwhrvHu3w
Batch-processing in Affinity Photo: https://www.youtube.com/watch?v=4qrQjD_0LyI und
https://affinity.help/photo2/de.lproj/index.html?page=pages/Macros_Batch/batchjobs.html&title=Die%20Stapelverarbeitung
WordPress-PlugIn (Converter for Media): https://de.wordpress.org/plugins/webp-converter-for-media/
Online-Konverter für AVIF und andere Dateiformate: https://squoosh.app/
Auch die freie Online-Bildbearbeitung Photopea exportiert AVIF: https://www.photopea.com/
Dateiformate im Vergleich: https://www.mediaevent.de/bilddatenformate-jpg-avif-png-webp/
Videotutorial „How to Install Homebrew on Mac“ (um Kommandozeilenprogramme zu installieren): https://www.youtube.com/watch?v=IWJKRmFLn-g
Terminal / Kommandozeile: https://www.giga.de/extra/linux/specials/linux-befehle/, https://wiki.ubuntuusers.de/Shell/Befehls%C3%BCbersicht/, macOS-Terminal – Das kleine Einmaleins der Kommandozeile: https://www.heise.de/ratgeber/Einfuehrung-in-die-macOS-Kommandozeile-Das-kleine-Terminal-Einmaleins-3463440.html, 7 nützliche CMD Befehle (solltest du kennen): https://www.youtube.com/watch?v=ZIzXVIq0lIo, The 50 Most Popular Linux & Terminal Commands – Full Course for Beginners: https://www.youtube.com/watch?v=ZtqBQ68cfJc, Beginner’s Guide to the Bash Terminal: https://www.youtube.com/watch?v=oxuRxtrO2Ag, https://www.shellbefehle.de/befehle/,