Responsive Bilder mit dem Render-Image-Template
AVIF, WebP und srcset aus einer einzigen Quelldatei
Moderne Browser können AVIF und WebP darstellen und wählen aus einem srcset die Auflösung, die zum aktuellen Viewport passt. Eine statische Seite kann diese Varianten nicht zur Laufzeit erzeugen – sie müssen beim Build vorliegen. Genau das übernimmt Hugo: Das Theme dieser Website rendert jedes Markdown-Bild über ein eigenes Template, das aus einer einzigen Quelldatei ein komplettes <picture>-Element mit mehreren Formaten und Auflösungen generiert.
Das Render-Image-Template
Hugo ruft für jedes Markdown-Bild in der Form  den dazugehörigen Image-Render-Hook auf. Das Template liegt unter layouts/_markup/render-image.html und erhält neben der Ziel-URL (Destination) auch den Alternativtext, einen optionalen Titel und weitere Attribute. Absolute URLs – also externe Bilder – werden nicht weiterverarbeitet und als schlichtes <img>-Element ausgegeben. Interne Pfade durchlaufen dagegen die Resource-Pipeline von Hugo.
Das Bild als Resource
Das Template ermittelt zunächst den relativen Pfad und lädt die Datei entweder als Resource der aktuellen Seite oder als globale Resource. Der Pfad wird ohne Language-Prefix referenziert, das Bild liegt einfach neben der Markdown-Datei:
content/de/posts/valheim_server/
├── index.md
└── start.png
Formate mit Process
Aus der Quelldatei erzeugt das Template mit der Methode Process konvertierte Varianten:
Process "avif"undProcess "webp"für die beiden<source>-Elemente,Process "png"als Fallback, wenn die Quelldatei selbst AVIF oder WebP ist.
So zeigt das schlichte <img>-Element – gedacht für Browser ohne AVIF- oder WebP-Unterstützung – immer ein breit unterstütztes Format, während moderne Browser das AVIF-Element nutzen. Dasselbe Bild, aber deutlich kleiner.
Auflösungen mit Resize
Für jedes Format erzeugt das Template zusätzlich verkleinerte Varianten. Resize skaliert dabei proportional, denn in der Spezifikation ist nur die Breite angegeben:
{{ $widths := slice 640 1024 1600 }}
{{ $srcset := slice }}
{{ range $width := $widths }}
{{ with $img.Resize (printf "%dx" $width) }}
{{ $srcset = $srcset | append (printf "%s %dw" .RelPermalink $width) }}
{{ end }}
{{ end }}
<source srcset="{{ delimit $srcset ", " }}"
type="{{ .MediaType }}"
sizes="(min-width: 50rem) 48.8rem, calc(100vw - 1.2rem)">
Die Zielbreiten stehen als Slice im Template. Die w-Deskriptoren im Srcset sagen dem Browser, wie breit jede Variante ist, und sizes teilt mit, wie breit das Bild im Layout gerendert wird: so breit wie die Spalte (maximal 48.8rem – 50rem minus Padding), auf schmalen Viewports die Viewport-Breite. Aus beidem kombiniert der Browser die passende Variante – auf dem Smartphone wird die 640-er-Variante geladen, auf einem großen Display mit hoher Pixel-Dichte die 1600-er.
Das Ergebnis
Aus der Zeile

wird beim Build – ein Beispiel ist der Valheim-Server – ein solches Element:
<picture>
<source srcset="/posts/valheim_server/start_hu_37b1ad7146920a96.avif 640w,
… 1024w, … 1600w"
type="image/avif" sizes="(min-width: 50rem) 48.8rem, calc(100vw - 1.2rem)">
<source srcset="/posts/valheim_server/start_hu_80ba7bffd149498.webp 640w,
… 1024w, … 1600w"
type="image/webp" sizes="(min-width: 50rem) 48.8rem, calc(100vw - 1.2rem)">
<img src="/posts/valheim_server/start_hu_9c53bb67a45ce1fd.png" alt="valheim-server"
width="1024" height="663">
</picture>
Die verarbeiteten Dateien schreibt Hugo mit Hash-Suffix in das Verzeichnis der Seite. Die <img>-Variante ist eine auf 1024px verarbeitete Fallback-Variante; die Attribute width und height reservieren den Platz im Layout, bevor das Bild geladen ist. Das CSS der Seite (max-width: 100% und height: auto) skaliert das Bild daraufhin proportional auf die Spaltenbreite – ohne height: auto würde die feste Höhenangabe das Bild verzerrt darstellen.
weitere Details
- Query und Fragment: Ein
?oder#in der Bild-URL wird am Fallback-srcerhalten. - Attribute: Zusätzliche Attribute aus dem Markdown, etwa eine
class, werden an das<picture>-Element übernommen. - Fehlende Dateien: Zeigt ein internes Bild auf eine nicht vorhandene Datei, warnt Hugo beim Build – der Build läuft also sauber durch, das Bild fehlt nur.
- Hochskalierung: Hugo skaliert kleinere Bilder auf die Zielbreite hoch, statt die Variante wegzulassen. Es lohnt sich daher, ausreichend große Originale abzulegen.