Verwendung performanter Next-Gen-Bilder in CSS mit image-set

Avatar of Ollie Williams
Ollie Williams am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Die CSS-Funktion image-set() wird in Chromium-basierten Browsern seit 2012 und in Safari seit Version 6 unterstützt. Kürzlich erfolgte die Unterstützung auch in Firefox 88. Tauchen wir ein und sehen wir, was wir heute mit image-set() tun können und was nicht.

Mehrere Auflösungen desselben Bildes

Das sagt die CSS-Spezifikation über image-set():

Die Bereitstellung der am besten geeigneten Bildauflösung für das Gerät eines Benutzers kann eine schwierige Aufgabe sein. Idealerweise sollten Bilder die gleiche Auflösung wie die Geräte haben, auf denen sie angezeigt werden, was von Benutzer zu Benutzer variieren kann. Andere Faktoren können jedoch in die Entscheidung einfließen, welches Bild gesendet werden soll. Wenn ein Benutzer beispielsweise eine langsame mobile Verbindung hat, bevorzugt er möglicherweise niedrigere Auflösungsbilder, anstatt auf ein großes Bild mit richtiger Auflösung zu warten.

Dies ist im Grunde ein CSS-Hintergrund-Äquivalent zum HTML-Attribut srcset für img-Tags. Durch die Verwendung von image-set können wir mehrere Auflösungen eines Bildes bereitstellen und dem Browser vertrauen, die beste Entscheidung darüber zu treffen, welches verwendet werden soll. Dies kann verwendet werden, um einen Wert für drei verschiedene CSS-Eigenschaften anzugeben: content, cursor und, am nützlichsten von allen, background-image.

.hero {
  background-image: image-set("platypus.png" 1x, "platypus-2x.png" 2x);
}

1x wird verwendet, um das Bild mit niedriger Auflösung zu identifizieren, während 2x verwendet wird, um das Bild mit hoher Auflösung zu definieren. x ist ein Alias von dppx, was für **dots per pixel unit** (Punkte pro Pixeleinheit) steht.

Chrome/Edge/Opera/Samsung Internet benötigen derzeit ein -webkit--Präfix. Wenn Sie Autoprefixer verwenden, wird dies automatisch gehandhabt. Safari benötigt das Präfix nicht mehr, verwendet aber eine ältere Syntax, die eine url()-Funktion zum Angeben des Bildpfads erfordert. Wir könnten auch ein normales background-image: url() einfügen, um Browser zu unterstützen, die image-set nicht unterstützen.

.hero {
  /* Fallback */
  background-image: url("platypus.png");

  /* Chrome/Edge/Opera/Samsung, Safari will fallback to this as well */
  background-image: -webkit-image-set(url("platypus.png") 1x, url("platypus-2x.png") 2x);

  /* Standard use */
  background-image: image-set("platypus.png" 1x, "platypus-2x.png" 2x);
}

Jetzt werden Benutzer auf teuren, schicken Geräten ein gestochen scharfes Bild sehen. Die Leistung wird für Benutzer mit langsamen Verbindungen oder günstigeren Bildschirmen verbessert, da ihr Browser automatisch das Bild mit niedrigerer Auflösung anfordert. Wenn Sie sicherstellen wollten, dass das Bild mit hoher Auflösung auf Geräten mit hoher Auflösung auch bei langsamen Verbindungen verwendet wird, könnten Sie stattdessen die Medienabfrage min-resolution anstelle von image-set verwenden. Mehr über das Ausliefern von scharfen Bildern für hochauflösende Bildschirme erfahren Sie in Jake Archibalds aktuellem Beitrag auf seinem Blog.

Das ist ziemlich cool, aber was ich wirklich will, ist die Möglichkeit, die neuesten Bildformate in CSS zu übernehmen und gleichzeitig ältere Browser zu berücksichtigen…

Neue Bildformate

Safari 14 hat die Unterstützung für WebP eingeführt. Es war der letzte moderne Browser, der dies tat, was bedeutet, dass das Bildformat jetzt überall unterstützt wird (außer im Internet Explorer). WebP ist nützlich, da es Bilder erzeugen kann, die oft kleiner sind als (aber die gleiche Qualität wie) JPG, PNG oder GIF.

Es tauchen auch eine ganze Reihe noch neuerer Bildformate auf. AVIF-Bilder sind schockierend klein. Chrome, Opera und Samsung Internet haben die Unterstützung für AVIF bereits eingeführt. In Firefox ist es bereits hinter einem Flag. Dieses Bildformat wird noch von vielen Design-Tools nicht unterstützt, aber Sie können Bilder mit der Squoosh-App, die vom Chrome-Team bei Google entwickelt wurde, in AVIF konvertieren. WebP 2, HEIF und JPEG XL könnten schließlich auch in Browsern landen. Das ist alles ziemlich aufregend, aber wir möchten, dass Browser, die diese neueren Formate nicht unterstützen, trotzdem einige Bilder erhalten. Glücklicherweise hat image-set() eine Syntax dafür.

Neue Bildformate durch Angabe eines Typs verwenden

Hinweis zur Browserunterstützung: Das Feature von image-set, über das ich gleich sprechen werde, hat derzeit eine ziemlich schlechte Browserunterstützung. Derzeit wird es nur in Firefox 89 unterstützt.

HTML unterstützt das <picture>-Element seit Jahren.

<picture>
  <source srcset="./kitten.avif" type="image/avif">
  <img src="./kitten.jpg" alt="a small kitten"> 
</picture>

image-set bietet das CSS-Äquivalent und ermöglicht die Verwendung von Next-Gen-Bildformaten durch Angabe des MIME-Typs des Bildes.

.div1 {
  background-image: image-set(
    "kitten.avif" type("image/avif"),
    "kitten.jpg" type("image/jpeg")
  );
}

Das Next-Gen-Bild steht zuerst, während das Fallback-Bild für ältere Browser an zweiter Stelle steht. Nur ein Bild wird heruntergeladen. Wenn der Browser AVIF nicht unterstützt, ignoriert er es und lädt nur das zweite von Ihnen angegebene Bild herunter. Wenn AVIF unterstützt wird, wird das Fallback-Bild ignoriert.

Im obigen Beispiel haben wir ein AVIF-Bild verwendet und ein JPEG als Fallback bereitgestellt, aber das Fallback könnte jedes weit verbreitete Bildformat sein. Hier ist ein Beispiel mit einem PNG.

.div2 {
  background-image: image-set(
    "puppy.webp" type("image/webp"),
    "puppy.png" type("image/png")
  );
}

In Chrome und Safari wird die Angabe des type noch nicht unterstützt. Das bedeutet, dass Sie image-set heute nur verwenden können, um verschiedene Auflösungen von weit verbreiteten Bildformaten anzugeben, aber nicht, um Rückwärtskompatibilität hinzuzufügen, wenn Sie WebP oder AVIF in diesen Browsern verwenden. Es sollte möglich sein, sowohl mehrere Auflösungen als auch mehrere Bildformate bereitzustellen, wenn Sie dazu geneigt sind.

.div2 {
  background-image: image-set( 
    "puppy.webp" type("image/webp") 1x,
    "puppy2x.webp" type("image/webp") 2x,
    "puppy.png" type("image/png") 1x,
    "puppy2x.png" type("image/png") 2x
  );
}

Hoffentlich verbessert sich die Browserunterstützung bald.

Verwendung von <picture> stattdessen für Hintergründe

Vielleicht brauchen Sie background-image gar nicht mehr. Wenn Sie moderne Bildformate verwenden möchten, können Sie möglicherweise das <picture>-Element verwenden, das eine bessere Browserunterstützung hat. Wenn Sie das Bild auf position: absolute setzen, ist es einfach, andere Elemente darüber anzuzeigen.

Als Alternative zur Verwendung von position: absolute ist CSS Grid eine weitere einfache Möglichkeit, HTML-Elemente zu überlagern.