Bilder mit hohem DPI-Wert für variable Pixeldichten

Boris Smus
Boris Smus

Eines der Merkmale der heutigen komplexen Gerätelandschaft ist, dass eine sehr große Auswahl an Bildschirmpixeldichten verfügbar ist. Einige Geräte verfügen über sehr hochauflösende Displays, während andere zurückbleiben. Anwendungsentwickler müssen eine Reihe von Pixeldichten unterstützen, was recht schwierig sein kann. Die Herausforderungen im mobilen Web ergeben sich durch mehrere Faktoren:

  • Große Auswahl an Geräten mit unterschiedlichen Formfaktoren.
  • Eingeschränkte Netzwerkbandbreite und Akkulaufzeit.

Im Hinblick auf Bilder besteht das Ziel von Web-App-Entwicklern darin, Bilder mit bester Qualität so effizient wie möglich bereitzustellen. In diesem Artikel werden einige nützliche Techniken vorgestellt, mit denen Sie dies heute und in naher Zukunft erreichen können.

Bilder nach Möglichkeit vermeiden

Bevor Sie diese Würmerform öffnen, bedenken Sie, dass das Web viele leistungsstarke Technologien bietet, die weitgehend unabhängig von Auflösung und DPI sind. Insbesondere Text, SVG und viele CSS-Elemente werden aufgrund der automatischen Pixelskalierungsfunktion (über devicePixelRatio) im Web „einfach funktionieren“.

Allerdings lassen sich Rasterbilder nicht immer vermeiden. Das kann z. B. der Fall sein, wenn Sie Assets erhalten, die sich mit reinem SVG/CSS nur schwer reproduzieren lassen, oder dass es sich um ein Foto handelt. Sie können das Bild zwar automatisch in SVG konvertieren, aber eine Vektorisierung von Fotos ist nicht sinnvoll, da vergrößerte Versionen in der Regel nicht gut aussehen.

Hintergrund

Die bisherigen Daten zur Anzeigedichte

Anfangs hatten Computerbildschirme eine Pixeldichte von 72 oder 96 dpi (dots per inch).

Die Pixeldichte von Displays wurde nach und nach verbessert. Dies ist hauptsächlich auf Mobilgeräte zurückzuführen, bei denen Nutzer ihre Smartphones näher ans Gesicht halten, um die Pixel besser sichtbar zu machen. Bis 2008 waren Smartphones mit 150 dpi die neue Norm. Der Trend zur erhöhten Bildschirmdichte hat sich fortgesetzt. Die neuen Smartphones von heute verfügen über 300-dpi-Displays (mit der Bezeichnung „Retina“ von Apple).

Der heilige Gral ist natürlich eine Darstellung, auf der Pixel vollständig unsichtbar sind. Was den Formfaktor eines Smartphones betrifft, kann die aktuelle Generation von Retina/HiDPI-Displays nah an diesem Ideal sein. Aber neue Klassen von Hardware und Wearables wie Project Glass werden wahrscheinlich weiterhin zu einer höheren Pixeldichte führen.

In der Praxis sollten Bilder mit niedriger Dichte auf neuen Bildschirmen genauso aussehen wie auf alten. Allerdings sehen die Bilder mit niedriger Dichte im Vergleich zu den scharfen Bildern, die Nutzer mit hoher Dichte gewohnt sind, irritierend und verpixelt aus. Im Folgenden finden Sie eine grobe Simulation, wie ein 1x-Bild auf einem 2x-Display aussieht. Im Gegensatz dazu sieht das 2x-Bild ziemlich gut aus.

Pavian 1x
Pavian 2x
Die Paviane haben unterschiedliche Pixeldichten.

Pixel im Web

Bei der Entwicklung des Webs hatten 99% der Bildschirme eine Auflösung von 96 dpi (oder es wird vorgetäuscht), und es wurden nur wenige Vorkehrungen getroffen, um diese Darstellung zu variieren. Aufgrund der großen Unterschiede bei Bildschirmgrößen und -dichten brauchten wir eine Standardmethode, damit Bilder bei verschiedenen Bildschirmdichten und Abmessungen gut aussehen.

In der HTML-Spezifikation wurde dieses Problem kürzlich angegangen, indem ein Referenzpixel definiert wurde, mit dem Hersteller die Größe eines CSS-Pixels bestimmen.

Anhand des Referenzpixels kann ein Hersteller die Größe des physischen Pixels des Geräts im Verhältnis zum Standard- oder idealen Pixel bestimmen. Dieses Verhältnis wird als Geräte-Pixel-Verhältnis bezeichnet.

Pixel-Verhältnis des Geräts berechnen

Angenommen, ein Smartphone hat einen Bildschirm mit einer physischen Pixelgröße von 180 Pixeln pro Zoll (ppi). Die Berechnung des Pixelverhältnisses des Geräts erfolgt in drei Schritten:

  1. Vergleichen Sie die tatsächliche Entfernung, bei der das Gerät gehalten wird, mit der Entfernung für das Referenzpixel.

    Laut der Spezifikation sind 28 Zoll die ideale Größe von 96 Pixeln pro Zoll. Da es sich jedoch um ein Smartphone handelt, halten Nutzer dieses Gerät näher ans Gesicht als einen Laptop. Nehmen wir an, diese Entfernung beträgt 18 Zoll.

  2. Multipliziere das Entfernungsverhältnis mit der Standarddichte (96 ppi), um die ideale Pixeldichte für die gegebene Entfernung zu erhalten.

    idealPixelDensity = (28/18) * 96 = 150 Pixel pro Zoll (ungefähr)

  3. Nehmen Sie das Verhältnis der physischen Pixeldichte zur idealen Pixeldichte, um das Pixelverhältnis des Geräts zu erhalten.

    devicePixelRatio = 180 ÷ 150 = 1,2

So wird devicePixelRatio berechnet.
Ein Diagramm mit einem Referenzpixel, das zeigt, wie „devicePixelRatio“ berechnet wird.

Wenn ein Browser jetzt wissen muss, wie er die Größe eines Bildes an den Bildschirm entsprechend der idealen oder Standardauflösung anpassen muss, bezieht er sich auf das Geräte-Pixel-Verhältnis von 1,2, das bedeutet, dass dieses Gerät für jedes ideale Pixel 1,2 physische Pixel hat. Die Formel, mit der zwischen den idealen (wie in der Webspezifikation definiert) und physischen Pixeln (Punkte auf dem Gerätebildschirm) gewechselt werden muss, lautet:

physicalPixels = window.devicePixelRatio * idealPixels

In der Vergangenheit haben Geräteanbieter devicePixelRatioss (DPRs) gerundet. iPhone und iPad von Apple melden die DPR 1 und die Retina-Äquivalente den Bericht 2. In der Preisvergleichsportal-Spezifikation wird empfohlen,

bezieht sich die Pixeleinheit auf die ganze Anzahl von Gerätepixeln, die sich am besten an das Referenzpixel annähern.

Ein Grund, warum Rundverhältnisse besser sein können, ist, dass sie zu weniger Subpixel-Artefakten führen können.

Die Realität der Gerätelandschaft ist jedoch viel vielfältiger, und Android-Smartphones haben oft einen Wert von 1, 5. Das Nexus 7-Tablet hat einen DPR von etwa 1,33, was aus einer ähnlichen Berechnung wie oben ergibt. Künftig wird es voraussichtlich mehr Geräte mit schwankenden DVR-Werten geben. Sie sollten daher nicht davon ausgehen, dass Ihre Clients ganzzahlige Notfallwiederherstellungen haben.

Übersicht über HiDPI-Bildtechniken

Es gibt viele Techniken, um das Problem zu lösen, die Bilder mit bester Qualität so schnell wie möglich anzuzeigen. Sie lassen sich grob in zwei Kategorien einteilen:

  1. Einzelne Bilder optimieren
  2. Auswahl zwischen mehreren Bildern optimieren

Einzelbild-Ansätze: Verwenden Sie nur ein Bild, aber gehen Sie dabei etwas cleverer vor. Diese Ansätze haben jedoch den Nachteil, dass Sie zwangsläufig die Leistung beeinträchtigen, da Sie HiDPI-Bilder auch auf älteren Geräten mit geringerem DPI-Wert herunterladen. Hier sind einige Ansätze für den Fall eines einzelnen Images:

  • Stark komprimiertes HiDPI-Bild
  • Richtig cooles Bildformat
  • Progressive-Bildformat

Methoden mit mehreren Bildern: Verwenden Sie mehrere Bilder, wählen Sie aber auf clevere Weise aus, welche geladen werden soll. Diese Ansätze verursachen Mehraufwand für den Entwickler, um mehrere Versionen desselben Assets zu erstellen und dann eine Entscheidungsstrategie zu entwickeln. So sehen die einzelnen Optionen aus:

  • JavaScript
  • Serverseitige Bereitstellung
  • CSS-Medienabfragen
  • Integrierte Browserfunktionen (image-set(), <img srcset>)

Stark komprimiertes HiDPI-Bild

Bilder kosten bereits beeindruckende 60% der Bandbreite, die für den Download einer durchschnittlichen Website aufgewendet wird. Wir erhöhen diese Zahl, indem wir allen Kunden HiDPI-Bilder zur Verfügung stellen. Wie viel größer wird es wachsen?

Ich habe einige Tests durchgeführt, um 1- und 2x-Bildfragmente in JPEG-Qualität mit 90, 50 und 20 Pixeln zu generieren. Hier ist ein Shell-Script, das ich mit ImageMagick verwendet habe, um sie zu generieren:

Ansichten – Beispiel 1 Ansichten – Beispiel 2. Kacheln – Beispiel 3
Beispiele von Bildern mit unterschiedlichen Komprimierungen und Pixeldichten

Angesichts dieser kleinen, unwissenschaftlichen Stichprobe scheint die Komprimierung großer Bilder einen guten Kompromiss zwischen Qualität und Größe zu bieten. Für mein Auge sehen stark komprimierte 2x-Bilder besser aus als unkomprimierte 1x-Bilder.

Natürlich ist das Bereitstellen von minderer Qualität und stark komprimierten 2-fachen Bildern auf 2-fachen Geräten schlechter als die Bereitstellung von Geräten mit höherer Qualität. Die oben beschriebene Methode führt außerdem zu Qualitätseinbußen bei der Bildqualität. Wenn Sie die Qualität (90 Bilder) mit der Qualität von 20 Bildern vergleichen, werden Sie einen Rückgang der Schärfe und Körnigkeit feststellen. Diese Artefakte sind möglicherweise nicht akzeptabel, wenn Bilder hoher Qualität wichtig sind (z. B. in einer Fotoanzeige-App) oder für App-Entwickler, die nicht zu Kompromissen bereit sind.

Der obige Vergleich wurde ausschließlich mit komprimierten JPEGs durchgeführt. Zwischen den weit verbreiteten Bildformaten (JPEG, PNG, GIF) gibt es viele Kompromisse. Das bringt uns zu...

Richtig cooles Bildformat

WebP ist ein ziemlich überzeugendes Bildformat, das sehr gut komprimiert wird, ohne dabei hohe Bildqualität zu erzielen. Sie wurde natürlich noch nicht überall implementiert.

Eine Möglichkeit ist die Überprüfung der Unterstützung von WebP über JavaScript. Sie laden ein 1 Pixel großes Bild über einen Data-URI, warten entweder auf das Auslösen von geladenen oder Fehlerereignissen und prüfen dann, ob die Größe korrekt ist. Modernizr wird mit einem solchen Skript zur Featureerkennung ausgeliefert, das über Modernizr.webp verfügbar ist.

Besser geht dies jedoch direkt in CSS mit der image()-Funktion. Bei einem WebP-Bild und einem JPEG-Fallback können Sie also Folgendes schreiben:

#pic {
  background: image("foo.webp", "foo.jpg");
}

Bei diesem Ansatz gibt es einige Probleme. Erstens ist image() überhaupt nicht allgemein implementiert. Zweitens: Obwohl die WebP-Komprimierung JPEG-Dateien aus dem Wasser entfernt, ist sie immer noch eine relativ schrittweise Verbesserung – laut dieser WebP-Galerie um etwa 30% kleiner. Daher reicht WebP allein nicht aus, um das Problem mit hohen DPI-Werten zu lösen.

Progressive-Bildformate

Progressive Bildformate wie JPEG 2000, Progressive JPEG, progressive PNG und GIF haben den (eher umstritten) Vorteil, dass das Bild vor dem vollständigen Laden an Ort und Stelle angezeigt wird. Dabei kann ein gewisser Größenaufwand anfallen, auch wenn es widersprüchliche Beweise dafür gibt. Jeff Atwood behauptete, dass der Progressive-Modus „die Größe von PNG-Bildern um etwa 20% und die Größe von JPEG- und GIF-Bildern um etwa 10% erhöht“. Stoyan Stefanov behauptete jedoch, dass der Progressive-Modus für große Dateien (in den meisten Fällen) effizienter ist.

Auf den ersten Blick sehen progressive Bilder sehr vielversprechend aus, wenn es darum geht, qualitativ hochwertige Bilder so schnell wie möglich bereitzustellen. Die Idee dahinter ist, dass der Browser den Download und die Decodierung eines Bildes beenden kann, sobald er weiß, dass zusätzliche Daten die Bildqualität nicht erhöhen (d. h., alle Verbesserungen der Grafikqualität sind Subpixel).

Verbindungen lassen sich zwar leicht beenden, der Neustart ist jedoch oft teuer. Bei einer Website mit vielen Bildern besteht der effizienteste Ansatz darin, eine einzelne HTTP-Verbindung aktiv zu halten und so lange wie möglich wiederzuverwenden. Wenn die Verbindung vorzeitig beendet wird, weil ein Bild ausreichend heruntergeladen wurde, muss der Browser eine neue Verbindung herstellen. Dies kann in Umgebungen mit niedriger Latenz wirklich langsam sein.

Eine Problemumgehung besteht darin, die Anfrage HTTP Range zu verwenden, mit der Browser einen Bytebereich angeben können, der abgerufen werden soll. Ein intelligenter Browser könnte eine HEAD-Anfrage stellen, um den Header abzurufen, ihn zu verarbeiten, zu entscheiden, wie viel des Bilds tatsächlich benötigt wird, und dann diesen abzurufen. Leider wird der HTTP-Bereich von Webservern schlecht unterstützt, sodass dieser Ansatz nicht praktikabel ist.

Eine offensichtliche Einschränkung bei diesem Ansatz besteht darin, dass Sie nicht auswählen können, welches Bild geladen werden soll, sondern nur die Identität desselben Bildes variieren. Dies trifft daher nicht auf den Anwendungsfall Art Direction zu.

Mit JavaScript entscheiden, welches Bild geladen werden soll

Der erste und naheliegendste Ansatz für die Entscheidung, welches Bild geladen werden soll, ist die Verwendung von JavaScript im Client. Auf diese Weise erfahren Sie alles über Ihren User-Agent und können das Richtige tun. Sie können das Pixelverhältnis des Geräts über window.devicePixelRatio bestimmen, die Bildschirmbreite und -höhe abrufen und eventuell sogar über „navigator.connection“ Netzwerkverbindungen prüfen oder eine gefälschte Anfrage senden, wie dies bei der Bibliothek foresight.js der Fall ist. Nachdem Sie alle diese Informationen erfasst haben, können Sie entscheiden, welches Bild geladen werden soll.

Es gibt ungefähr eine Million JavaScript-Bibliotheken, die in etwa die oben genannten Bibliotheken verwenden. Leider ist keine davon besonders gut.

Ein großer Nachteil dieses Ansatzes besteht darin, dass bei der Verwendung von JavaScript das Laden des Bildes verzögert wird, bis der Look-Ahead-Parser abgeschlossen ist. Das bedeutet, dass die Bilder erst heruntergeladen werden, nachdem das pageload-Ereignis ausgelöst wurde. Weitere Informationen dazu finden Sie in Jason Grigsbys Artikel.

Entscheiden, welches Image auf dem Server geladen werden soll

Sie können die Entscheidung auf die Serverseite auslagern, indem Sie benutzerdefinierte Anfrage-Handler für jedes bereitgestellte Image schreiben. Dieser Handler prüft die Retina-Unterstützung anhand des User-Agents (der einzigen Information, die an den Server weitergeleitet wird). Je nachdem, ob die serverseitige Logik HiDPI-Assets bereitstellen möchte, laden Sie das entsprechende Asset (nach einer bekannten Konvention benannt).

Leider stellt der User-Agent nicht unbedingt genügend Informationen bereit, um zu entscheiden, ob ein Gerät Bilder mit hoher oder niedriger Qualität empfangen soll. Selbstverständlich ist alles, was mit dem User-Agent zu tun hat, ein Hack und sollte nach Möglichkeit vermieden werden.

CSS-Medienabfragen verwenden

Da CSS-Medienabfragen deklarativ sind, können Sie Ihre Absicht angeben und dem Browser ermöglichen, das Richtige für Sie zu tun. Zusätzlich zur häufigsten Verwendung von Medienabfragen – dem Abgleich der Gerätegröße – können Sie auch devicePixelRatio abgleichen. Die zugehörige Medienabfrage hat das Verhältnis von „Device-Pixel-Ratio“ und zugehörige Mindest- und Höchstvarianten sind erwartungsgemäß zugeordnet. Wenn Sie Bilder mit hoher DPI-Werten laden möchten und das Geräte-Pixel-Verhältnis einen Schwellenwert überschreitet, können Sie Folgendes tun:

#my-image { background: (low.png); }

@media only screen and (min-device-pixel-ratio: 1.5) {
  #my-image { background: (high.png); }
}

Es wird etwas komplizierter, wenn alle Anbieterpräfixe enthalten sind, insbesondere aufgrund der irgendeiner Unterschiede bei der Platzierung der Präfixe „min“ und „max“:

@media only screen and (min--moz-device-pixel-ratio: 1.5),
    (-o-min-device-pixel-ratio: 3/2),
    (-webkit-min-device-pixel-ratio: 1.5),
    (min-device-pixel-ratio: 1.5) {

  #my-image {
    background:url(high.png);
  }
}

Mit diesem Ansatz profitieren Sie wieder von den Vorteilen des Look-Ahead-Parsings, das mit der JS-Lösung verloren gegangen ist. Außerdem können Sie responsive Haltepunkte flexibel auswählen (z. B. Bilder mit niedriger, mittlerer und hoher DPI-Werten), was beim serverseitigen Ansatz verloren gegangen ist.

Leider ist es immer noch etwas unhandlich und führt zu seltsam aussehendem CSS (oder erfordert eine Vorverarbeitung). Außerdem ist dieser Ansatz auf CSS-Eigenschaften beschränkt, sodass es keine Möglichkeit gibt, ein <img src> festzulegen. Alle Bilder müssen Elemente mit einem Hintergrund sein. Wenn Sie sich außerdem ausschließlich auf das Pixelverhältnis des Geräts verlassen, kann es in Situationen kommen, in denen Ihr High-DPI-Smartphone ein riesiges 2-faches Bild-Asset über eine EDGE-Verbindung herunterlädt. Das ist nicht die beste User Experience.

Neue Browserfunktionen verwenden

In letzter Zeit wurde die Unterstützung von Webplattformen für das Problem mit Bildern mit hoher DPI-Werten diskutiert. Apple ist kürzlich in diesen Bereich eingedrungen und hat die CSS-Funktion image-set() in WebKit integriert. Daher wird es sowohl von Safari als auch von Chrome unterstützt. Da es sich um eine CSS-Funktion handelt, löst image-set() nicht das Problem für <img>-Tags. Geben Sie @srcset ein. Damit wird dieses Problem behoben, zum Zeitpunkt dieses Schreibens hat es aber (noch!) keine Referenzimplementierungen. Im nächsten Abschnitt werden image-set und srcset näher erläutert.

Browserfunktionen zur Unterstützung hoher DPI-Werte

Letztendlich hängt die Entscheidung für Ihren Ansatz von Ihren individuellen Anforderungen ab. Alle oben genannten Ansätze haben jedoch ihre Nachteile. Sobald image-set und srcset allgemein unterstützt werden, sind sie die geeignete Lösung für dieses Problem. Lassen Sie uns vorerst über einige Best Practices sprechen, die uns der idealen Zukunft so nah wie möglich bringen können.

Erstens: Wie unterscheiden sich diese beiden? Nun, image-set() ist eine CSS-Funktion, die als Wert der CSS-Eigenschaft „Hintergrund“ verwendet werden kann. „srcset“ ist ein Attribut, das für <img>-Elemente spezifisch ist, mit ähnlicher Syntax. Mit beiden Tags können Sie Bilddeklarationen angeben, aber mit dem Attribut srcset lässt sich auch festlegen, welches Bild basierend auf der Größe des Darstellungsbereichs geladen werden soll.

Best Practices für Image-Set

Die CSS-Funktion image-set() ist mit dem Präfix -webkit-image-set() verfügbar. Die Syntax ist ziemlich einfach. Sie besteht aus einer oder mehreren durch Kommas getrennten Bilddeklarationen, die aus einem URL-String oder einer url()-Funktion sowie der zugehörigen Auflösung bestehen. Beispiel:

background-image:  -webkit-image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);

Dadurch weiß der Browser, dass zwei Bilder zur Auswahl stehen. Das eine ist für 1x-Displays, das andere für 2x-Displays optimiert. Der Browser kann dann anhand verschiedener Faktoren auswählen, welcher geladen werden soll. Dazu gehören unter anderem die Netzwerkgeschwindigkeit, sofern der Browser intelligent genug ist (soweit ich weiß, dass er derzeit noch nicht implementiert ist).

Der Browser lädt nicht nur das richtige Bild, sondern skaliert es entsprechend. Mit anderen Worten: Der Browser geht davon aus, dass zwei Bilder doppelt so groß sind wie ein 1-faches Bild und skaliert das 2-fache Bild also um den Faktor 2 herunter, sodass das Bild auf der Seite die gleiche Größe hat.

Anstelle von 1x, 1, 5x oder Nx können Sie auch eine bestimmte Pixeldichte des Geräts in dpi angeben.

Das funktioniert gut, außer in Browsern, die die image-set-Eigenschaft nicht unterstützen, bei denen überhaupt kein Bild angezeigt wird. Das ist eindeutig schlecht, daher müssen Sie ein Fallback (oder eine Reihe von Fallbacks) verwenden, um dieses Problem zu beheben:

background-image: url(icon1x.jpg);
background-image: -webkit-image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);
/* This will be useful if image-set gets into the platform, unprefixed.
    Also include other prefixed versions of this */
background-image: image-set(
  url(icon1x.jpg) 1x,
  url(icon2x.jpg) 2x
);

Mit dem Befehl oben wird das entsprechende Asset in Browsern geladen, die Imageset unterstützen. Andernfalls wird auf das 1x-Asset zurückgesetzt. Der offensichtliche Nachteil ist, dass die image-set()-Browserunterstützung gering ist, die meisten User-Agents aber das 1x-Asset erhalten.

In dieser Demo wird das image-set() verwendet, um das richtige Bild zu laden. Wenn diese CSS-Funktion nicht unterstützt wird, wird auf das 1x-Asset zurückgegriffen.

Sie fragen sich jetzt vielleicht, warum nicht einfach nur Polyfill (d. h. ein JavaScript-Shim für image-set()) erstellt und für einen Tag aufgerufen wird. Wie sich herausstellt, ist es ziemlich schwierig, effiziente Polyfills für CSS-Funktionen zu implementieren. Eine ausführliche Erläuterung dafür finden Sie in dieser Diskussion im „www-Stil“.

Bild-srcset

Hier ist ein Beispiel für srcset:

<img alt="my awesome image"
  src="banner.jpeg"
  srcset="banner-HD.jpeg 2x, banner-phone.jpeg 640w, banner-phone-HD.jpeg 640w 2x">

Neben den von image-set bereitgestellten x-Deklarationen verwendet das srcset-Element auch w- und h-Werte, die der Größe des Darstellungsbereichs entsprechen. So wird versucht, die relevanteste Version bereitzustellen. Oben würde „banner-phone.jpeg“ für Geräte mit einer Breite des Darstellungsbereichs unter 640 px, „banner-phone-HD.jpeg“ für Geräte mit kleinen Bildschirmen mit hohem DPI-Wert, banner-HD.jpeg für Geräte mit hoher DPI und Bildschirmgröße über 640 px und banner.jpeg für alles andere bereitstellen.

„image-set“ für Bildelemente verwenden

Da das srcset-Attribut von img-Elementen in den meisten Browsern nicht implementiert ist, kann es verlockend sein, die img-Elemente durch <div>s mit Hintergründen zu ersetzen und den Image-Set-Ansatz zu verwenden. Dies funktioniert mit Vorsichtsmaßnahmen. Der Nachteil hier ist, dass das <img>-Tag einen langfristigen semantischen Wert hat. In der Praxis ist dies vor allem aus Gründen der Web-Crawler und der Zugänglichkeit wichtig.

Wenn Sie letztendlich -webkit-image-set verwenden, sind Sie möglicherweise versucht, die CSS-Eigenschaft für den Hintergrund zu verwenden. Der Nachteil dieses Ansatzes besteht darin, dass Sie die Bildgröße angeben müssen. Dies ist jedoch nicht bekannt, wenn Sie ein Nicht-1x-Bild verwenden. Alternativ können Sie die CSS-Eigenschaft „content“ so verwenden:

<div id="my-content-image"
  style="content: -webkit-image-set(
    url(icon1x.jpg) 1x,
    url(icon2x.jpg) 2x);">
</div>

Dadurch wird das Bild automatisch an „devicePixelRatio“ skaliert. Sehen Sie sich dieses Beispiel der obigen Technik in Aktion an. Für Browser, die image-set nicht unterstützen, gibt es zusätzlich ein Fallback auf url().

Polyfilling mit srcset

Eine praktische Funktion von srcset ist, dass sie über ein natürliches Fallback verfügt. Wenn das srcset-Attribut nicht implementiert ist, können alle Browser das src-Attribut verarbeiten. Da es sich nur um ein HTML-Attribut handelt, können Polyfills mit JavaScript erstellt werden.

Dieser Polyfill wird mit Einheitentests geliefert, um sicherzustellen, dass er der Spezifikation so weit wie möglich entspricht. Außerdem gibt es Prüfungen, die verhindern, dass der Polyfill Code ausführt, wenn srcset nativ implementiert ist.

Hier ist eine Demo des Polyfill in Aktion.

Fazit

Es gibt keinen Zaubertrick, um das Problem von Bildern mit hohem DPI-Wert zu lösen.

Die einfachste Lösung ist, auf Bilder zu verzichten und stattdessen SVG und CSS zu verwenden. Das ist jedoch nicht immer realistisch, insbesondere wenn Ihre Website Bilder in hoher Qualität enthält.

Ansätze in JS und CSS sowie die serverseitige Verwendung haben alle ihre Stärken und Schwächen. Der vielversprechendste Ansatz ist jedoch die Nutzung neuer Browserfunktionen. Obwohl die Browserunterstützung für image-set und srcset noch nicht vollständig ist, gibt es heute vernünftige Alternativen.

Zusammenfassend lässt sich sagen, dass ich folgende Empfehlungen erhalte: