Der Begriff „responsive images“ steht mittlerweile für „responsive Bilder in HTML“, also die Attribute srcset und sizes für <img> sowie das <picture>-Element. Aber wie spiegeln sich die Möglichkeiten, die diese Dinge bieten, in CSS wider?
CSS war in den letzten Jahren generell kaum am Weg der responsiven Bilder beteiligt. Das hat gute Gründe: CSS verfügt bereits über die Werkzeuge. Responsive Images war in gewisser Weise nur ein Nachziehen dessen, was CSS bereits konnte. Schauen wir uns das mal an.
srcset in CSS
In HTML sieht srcset so aus (entnommen von der Picturefill-Website)
<img srcset="
examples/images/image-384.jpg 1x,
examples/images/image-768.jpg 2x
" alt="…">
Ein Bild für 1x-Displays, ein größeres Bild für 2x-Displays. Wenn wir dasselbe tun wollten, nur als background-image in CSS, könnten wir das so machen:
.img {
background-image: url(examples/images/image-384.jpg);
}
@media
(-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.img {
background-image: url(examples/images/image-768.jpg);
}
}
Es gibt hier jedoch einen Unterschied. Soweit ich das verstehe, ist die Art und Weise, wie srcset spezifiziert ist, eher ein Vorschlag. Das Attribut und der Wert liefern Informationen darüber, was verfügbar ist, und der Browser entscheidet, was im Moment am besten ist. Oder zumindest *könnte* er das, wenn Browser es so implementieren würden. Mit einer @media-Abfrage wird das deklarierte auch so umgesetzt.
Auflösungsmedienabfragen werden recht gut unterstützt

Es gibt auch noch eine andere Methode, die tatsächlich näher daran ist, wie srcset funktioniert, und das ist die Verwendung der image-set()-Funktion in CSS.
.img {
background-image: url(examples/images/image-384.jpg);
background-image:
-webkit-image-set(
url(examples/images/image-384.jpg) 1x,
url(examples/images/image-768.jpg) 2x,
);
background-image:
image-set(
url(examples/images/image-384.jpg) 1x,
url(examples/images/image-768.jpg) 2x,
);
}
Sie hat etwas weniger Unterstützung als Auflösungsabfragen.

Sie kommt srcset viel näher, nicht nur weil die Syntax ähnlich ist, sondern weil sie dem Browser eine Mitsprache erlaubt. Laut der (noch im Entwurf befindlichen) Spezifikation
Die image-set()-Funktion ermöglicht es einem Autor, die meisten dieser Probleme zu ignorieren, indem einfach mehrere Auflösungen eines Bildes bereitgestellt werden und der UA entscheidet, welche in einer bestimmten Situation am besten geeignet ist.
Es gibt keinen perfekten 1:1 Ersatz für srcset in CSS, aber das hier kommt dem schon ziemlich nahe.
sizes in CSS
Das sizes-Attribut in HTML hat eine *sehr direkte* Beziehung zu CSS. Tatsächlich besagt es im Grunde: *„So beabsichtige ich, dieses Bild in CSS zu skalieren, und ich lasse dich das jetzt wissen, weil du diese Information vielleicht genau jetzt brauchst und nicht warten kannst, bis CSS heruntergeladen ist.“*
Beispiel
<img
sizes="(min-width: 40em) 80vw, 100vw"
srcset=" ... "
alt="…">
Dies setzt etwas wie das hier im CSS voraus:
img {
width: 100%;
}
@media (min-width: 40em) {
/* Probably some parent element that limits the img width */
main {
width: 80%;
}
}
Aber sizes allein tut nichts. Man kombiniert es mit srcset, das bekannte Breiten liefert, damit der Browser eine Wahl treffen kann. Nehmen wir mal nur ein Paar Bilder wie:
<img
sizes="(min-width: 400px) 80vw, 100vw"
srcset="examples/images/small.jpg 375w,
examples/images/big.jpg 1500w"
alt="…">
Die Informationen im obigen Markup geben dem Browser, was er braucht, um das beste Bild für ihn zu ermitteln. Der Browser kennt 1) seine eigene Viewport-Größe und 2) seine eigene Pixeldichte.
Vielleicht ist der Browser-Viewport 320 Pixel breit und es ist ein 1x-Display. Er weiß nun auch, dass er dieses Bild mit 100vw anzeigen wird. Also muss er zwischen den beiden bereitgestellten Bildern wählen. Er macht ein paar Berechnungen.
375 (Größe von Bild Nr. 1) / 320 (verfügbare Pixel zur Anzeige des Bildes) = 1,17
1500 (Größe von Bild Nr. 2) / 320 (verfügbare Pixel zur Anzeige des Bildes) = 4,69
1,17 ist näher an 1 (es ist ein 1x-Display), daher gewinnt das 375w-Bild. Es wird versuchen, nicht darunter zu gehen, also würde 1,3 besser sein als 0,99, soweit ich das verstehe.
Nehmen wir an, es war ein 2x-Display. Das verdoppelt die benötigten Pixel zur Anzeige der Bilder, also ist die Berechnung:
375 / 640 = 0.59
1500 / 640 = 2.34
Hier gewinnt 2,34, und es wird das 1500w-Bild angezeigt. Wie wäre es mit einem 1x-Display mit einem 1200px-Viewport?
375 / (80% von 1200) = 0,39
1500 / (80% von 1200) = 1,56
Hier gewinnt das 1500w-Bild.
Das ist irgendwie seltsam und knifflig, in CSS zu schreiben. Wenn wir *nur* an 1x-Displays denken, landen wir bei Logik wie…
- Wenn der Viewport kleiner als 375px ist, verwenden Sie das 375w-Bild.
- Wenn der Viewport größer als 375px, aber kleiner als 400px ist, verwenden Sie das 1500w-Bild (da wir sonst hochskalieren würden).
- Bei 400px wird das Bild 80vw breit, daher ist es sicher, das 375w-Bild für ein kleines bisschen zu verwenden (zwischen 400px und 468px).
- Über 468px hinaus verwenden Sie das 1500w-Bild.
Das könnten wir so schreiben:
img {
background-image: url(small.jpg);
}
/* Only override this if one of the conditions for the 1500w image is met */
@media
(min-width: 375px) and (max-width: 400px),
(min-width: 468px) {
main {
background-image: url(large.jpg);
}
}
In diesem speziellen Fall, einem 2x-Display, werden selbst bei einer wirklich schmalen Breite von 300px immer noch 600px für eine Mindestqualität von 1,0 benötigt, daher würden wir das auch zur Logik hinzufügen:
.img {
background-image: url(small.jpg);
}
/* Only override this if one of the conditions for the 1500w image is met */
@media
(min-width: 375px) and (max-width: 400px),
(min-width: 468px),
(-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.img {
background-image: url(large.jpg);
}
}
Die Komplexität steigt exponentiell mit der Anzahl der Breakpoints (Größen) und der Anzahl der bereitgestellten Bilder. Und es ist immer noch kein perfekter Ersatz für das, was responsive Bilder (in HTML) können, da es dem Browser keine Diskretion überlässt (z. B. die Möglichkeit für einen Browser, andere Faktoren [d. h. Bandbreite] zu berücksichtigen, um ein Bild auszuwählen).
picture in CSS
Ein Beispiel
<picture>
<source srcset="extralarge.jpg" media="(min-width: 1000px)">
<source srcset="large.jpg" media="(min-width: 800px)">
<img srcset="medium.jpg" alt="…">
</picture>
Diese Art von Sache ist eine ziemlich direkte Umwandlung in Medienabfragen. Die genauen Medienabfragen sind zum Kopieren da.
.img {
background-image: url(medium.jpg);
}
@media (min-width: 800px) {
.img {
background-image: url(large.jpg);
}
}
@media (min-width: 1000px) {
.img {
background-image: url(extralarge.jpg);
}
}
Keine Überraschung, das kann komplizierter werden, denn srcset kann auch innerhalb des picture-Elements seine Wirkung entfalten.
<picture>
<source srcset="large.jpg, extralarge.jpg 2x" media="(min-width: 800px)">
<img srcset="small.jpg, medium.jpg 2x" alt="…">
</picture>
Was sich übersetzt zu:
.img {
background-image: url(small.jpg);
}
@media
(-webkit-min-device-pixel-ratio: 2),
(min-resolution: 192dpi) {
.img {
background-image: url(medium.jpg);
}
}
@media
(min-width: 800px) {
.img {
background-image: url(large.jpg);
}
}
@media
(-webkit-min-device-pixel-ratio: 2) and (min-width: 800px),
(min-resolution: 192dpi) and (min-width: 800px) {
.img {
background-image: url(extralarge.jpg);
}
}
Auch hier ist es nur eine Frage der Zeit, bis die Komplexität explodiert, wenn man ein paar weitere Bilder und Bedingungen hinzufügt. Mit image-set() etwas besser.
.img {
background-image: url(small.jpg);
background-image:
-webkit-image-set(
"small.jpg" 1x,
"medium.jpg" 2x,
);
background-image:
image-set(
"small.jpg" 1x,
"medium.jpg" 2x,
);
}
@media
(min-width: 800px) {
.img {
background-image: url(large.jpg);
background-image:
-webkit-image-set(
"large.jpg" 1x,
"extralarge.jpg" 2x,
);
background-image:
image-set(
"large.jpg" 1x,
"extralarge.jpg" 2x,
);
}
}
Könnten Mixins helfen?
Wahrscheinlich? Ich würde gerne ein Sass @mixin sehen, das all diese Parameter aufnimmt, die Bildgrößen berücksichtigt (die es selbst durch Zugriffe auf die Festplatte ermittelt) und daraus qualitativ hochwertigen Responsive-Images-in-CSS-Code generiert. Vielleicht gibt es sogar eine Möglichkeit, Auflösungsabfragen und image-set()-Syntaxen zu kombinieren?
Tun wir das wirklich?
Ich bin neugierig, wie viele Leute aktiv responsive Bilder in CSS behandeln. Vielleicht sogar auf eine Art Mittelweg, indem sie nur größere Bilder bei größeren Breakpoints austauschen? Ich frage mich, ob die Akzeptanz von responsive Bildern in CSS geringer ist als die von Picture/srcset, da letzteres oft automatisiert ist?
Die Srcsets haben mich immer verrückt gemacht. Danke, Chris!
image-setscheint definitiv der richtige Weg zu sein, aber bis die Browserunterstützung zunimmt, muss ich es mit einer Kombination aus@supportsund JavaScript-Erkennung implementieren. Im schlimmsten Fall gebe ich dem Browser das mobile Bild und ersetze es dann so schnell wie möglich per JavaScript durch eine browser-auflösungsabhängige Alternative.Danke für den Artikel. Ich finde die von Ihnen am Ende erwähnte Methode für den Moment am einfachsten (Austausch von Hintergrundbildern bei größeren Breakpoints). Normalerweise verwende ich ein mobiles Bild und ein Vollbildbild, um die Dinge einfach zu halten.
Ja, das ist es, was ich mache. Ich benutze einen einfachen Mixin, um das passende Hintergrundbild basierend auf den Einträgen in meiner Breakpoint-Map zu laden. Nichts Besonderes, aber es erfüllt seinen Zweck, und am wichtigsten ist, dass ich genau weiß, was in einem bestimmten Szenario geladen wird.
Toller Artikel Chris, ich kannte viele der von Ihnen behandelten Informationen nicht. Ich benutze derzeit nur das srcset-Attribut für meine persönliche Website (die ich nicht verlinken werde). Ich bin mir unsicher, wie ich das sizes-Attribut verwenden soll... also wenn Sie mir die Syntax erklären könnten, wäre ich sehr dankbar. Auf jeden Fall ein toller Artikel.
Wie wäre es mit
Width: auto;
Height: auto;
Max-height: auto;
Max-width: auto;
Und dem Zuweisen einer festen Dimension zum übergeordneten Element basierend auf verschiedenen Bildschirmgrößen?
Sagen wir
Width: 160px;
Height: 160px;
Der Sinn dahinter ist, nur das beste Bild für Ihr Gerät zu laden, damit Sie nicht auf jedem Gerät ein sehr hochauflösendes Bild herunterladen müssen.
Danke für den Artikel, Chris. Ich bin bei Yaphi. Ich tausche Hintergrundbilder bei verschiedenen Breakpoints aus und verwende nie mehr als 2 oder 3 Bilder. Desktop, Mobile und manchmal eins extra, um ein Masthead-Bild + CTA zu handhaben, das zusammenbricht. Halte es einfach.
Hey, netter Beitrag!
Wir haben es in unserem Unternehmen genutzt, um die heruntergeladene Bildgröße zu reduzieren, besonders bei Vollbild-Bildern kann dies die Bandbreite der Website von einigen MB auf unter ein MB reduzieren. Wir verwenden meist die HTML-Version, da alle unsere Bilder zur Laufzeit hochgeladen werden.
Das Problem, das ich sehe, ist, dass es schwierig ist, es richtig zu integrieren, sobald man Bootstrap-Spalten verwendet, mit unterschiedlichen Breakpoints.
Ich würde Ihnen dringend empfehlen, sich Cloudinary oder ImgIX anzusehen, um diese Dinge automatisch einzurichten. Zwar können Sie das alles selbst einrichten, wenn es erforderlich ist, aber diese Unternehmen sind beide erschwinglich und leisten wirklich erstaunliche Arbeit. Übrigens, ich bin in keiner Weise verbunden und bekomme auch kein Geld dafür; ich bin nur ein Nutzer beider auf verschiedenen Projekten und es war großartig, mich nicht mehr mit Bildproblemen auseinandersetzen zu müssen.
Unabhängig davon, danke für den wie immer guten Beitrag, Chris!
Toller Artikel. Ich habe srcset auf ein paar Websites verwendet, um die abscheuliche Art und Weise zu beheben, wie einige Browser Galerien handhabten.
Es lohnt sich zu erwähnen
https://github.com/square/apropos
apropos sieht wie ein vielversprechender Ansatz aus, danke dafür!
Ich habe mit https://github.com/paper-leaf/waldo auf meinem letzten Projekt herumgespielt, zugegeben, dies ist mehr PHP als CSS und stark auf WP / ACF basiert, aber meiner Meinung nach ist es trotzdem erwähnenswert.
Für Hintergrundbilder ist es viel einfacher, einen Mixin zu haben, der das richtige Bild bei einem bestimmten Breakpoint lädt, aber was Sie im Artikel behandeln, ist interessant für Inline-Bilder. Danke!
Guter Artikel, aber während die vorgeschlagenen Lösungen einige Probleme lösen mögen, verstoßen Hintergrundbilder auf IMG gegen HTML-Semantik und beeinträchtigen die Barrierefreiheit.
Ein img soll eine Bedeutung haben, die den Inhalt ergänzt, während Hintergrundbilder für dekorative Zwecke gedacht sind.
Ich behaupte keineswegs, dass Sie ein Inhaltsbild in ein CSS-Hintergrundbild verschieben sollten.