Gibt es ein srcset-Äquivalent für das CSS-Hintergrundbild?

88

imgwith srcsetattribute scheint eine großartige Möglichkeit zu sein, reaktionsschnelle Bilder zu erstellen. Gibt es eine äquivalente Syntax, die in CSS funktioniert?background-image Eigenschaft ?

HTML

<img src="small.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" alt="yah">

CSS

.mycontainer {
    background: url(?something goes here?);
}
Martin Algesten
quelle

Antworten:

81

image-setist die entsprechende CSS-Funktion. Wir sollten der Spezifikation eine äquivalente srcset-Funktionalität hinzufügen (Ressourcen entsprechend ihrer Dimensionen definieren).

Derzeit ist es nur in Safari, Chrome und Opera mit dem -webkit-Präfix implementiert und unterstützt nur die xDeskriptoren.

Yoav Weiss
quelle
1
Gibt es einen anmutigen Fallback oder eine Polyfill, die dies unterstützt?
Rachel Cantor
5
@RachelCantor Wäre ein Fallback notwendig? Nur moderne Geräte hätten sowieso Retina-Bildschirme, hätte ich gedacht?
James Kemp
3
Nur die xDeskriptoren zu unterstützen scheint sinnlos, ich meine, ein Hintergrundbild könnte auf einem 2x 'Retina'-Desktop (5120w) in voller Breite sein, was auf einem Handy mit 2x (720w) ein lächerlich großes Bild ist, das jedes mobile Gerät sogar als Webseite betrachten kann Hintergrund. Selbst die Verwendung von Medienabfragen mit maximaler Breite für einige verschiedene Größen ist nicht besonders hilfreich, da der Hintergrundcontainer nicht die maximale Breite und die maximale Bildschirmbreite aufweist.
Chris Seufert
1
Also, wenn ein Browser Image-Set nicht unterstützt, was ist der Fallback?
O.MeeKoh
22

Ziemlich sicher, dass:

background: -webkit-image-set( url('path/to/image') 1x, url('path/to/high-res-image') 2x );

funktioniert genauso. Der Browser überprüft die Bilder, um festzustellen, welche am besten passen, und verwendet diese.

SRing
quelle
2
Im Jahr 2018 wird dies immer noch nicht von allen Browsern unterstützt. caniuse.com/#search=image-set
BadHorsie
14

Ein anderer Ansatz, der offen gesagt robuster ist, besteht darin, die Eigenschaften und Optionen von Hintergrundbildern an ein Bild mit dem Attribut srcset anzupassen.

Stellen Sie dazu das Bild auf Breite ein: 100%; Höhe: 100%; und Objektanpassung: abdecken oder enthalten.

Hier ist ein Beispiel:

.pseudo-background-img-container {
  position: relative;
  width:400px;
  height: 200px;
}
.pseudo-background-img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
<div class="pseudo-background-img-container">

<img class="pseudo-background-img" src="https://cdn3.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep.jpg" srcset="https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep.jpg 640w, https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep-280x175.jpg 280w, https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep-432x270.jpg 432w, https://cdn0.tnwcdn.com/wp-content/blogs.dir/1/files/2016/12/Keep-216x135.jpg 216w" sizes="(max-width: 640px) 100vw, 640px">

</div>

Dies ist möglicherweise nicht der beste Ansatz für alle, aber ich kann mir vorstellen, dass ohne Javascript-Problemumgehung die gewünschten Ergebnisse erzielt werden.

Parks
quelle
1
src-set berücksichtigt nicht die Bildbreite, sondern nur die Containerbreite für object-fit: cover. Dies bedeutet, dass, wenn Ihr img-Tag beispielsweise 50 Pixel breit, aber 1000 Pixel hoch ist, das Bild, das die 50 Pixel Breite erfüllt, geladen und gedehnt wird, um es anzupassen, möglicherweise von 240 W auf 1500 Pixel Breite skaliert, um nur ein 50 Pixel-Slice anzuzeigen.
Chris Seufert
10

Für eine Polyfüllung können Sie ein Bild mit srcset als Mechanismus zum Herunterladen der richtigen Bildgröße verwenden. Anschließend können Sie es mit JS ausblenden und das Hintergrundbild eines übergeordneten Elements festlegen.

Hier ist eine Geige: http://jsbin.com/garetikubu/edit?html,output

Die Verwendung onloadund das Einfügen des JS als Blockierungsskript in das <head>ist wichtig. Wenn Sie das Skript später <body>einfügen (z. B. am Ende von ), können Sie eine Race-Bedingung erhalten, bei der img.currentSrc noch nicht vom Browser festgelegt wurde. Warten Sie am besten, bis es geladen ist.

In diesem Beispiel können Sie sehen, wie das Originalbild heruntergeladen wird. Sie können es einfach mit etwas CSS ausblenden.

Weston
quelle
Interessant. Ich hätte erwartet, dass das Bild dabei zweimal geladen wird. Es scheint jedoch nicht.
Perry
8

Sie können Medienabfragen für Ihren Zweck verwenden. So einfach ist das:

.mycontainer {    
    background-image:url("img/image-big.jpg"); // big image   
}

@media(max-width: 768px){
   .mycontainer {
        background-image:url("img/image-sm.jpg"); // small image  
    }
}

Und ich denke, es funktioniert in jedem Browser, der Medienabfragen unterstützt;)

gtamborero
quelle
2
Wenn Ihr Bild so eingestellt ist, dass es einen Container abdeckt, wird das auf die Höhe gestreckte Bild nicht berücksichtigt. Das Feld kann zwei- oder dreimal so hoch wie die native Bildbreite sein und sieht daher von sehr schlechter Qualität aus.
Chris Seufert
3

Ähnliche Lösung mit <picture>Element: Tutorial hier

Fall des Tutorials:

Ich bezweifle, dass das Hauptmotiv meines Bildes zu klein wird, wenn ich dasselbe Bild für eine kleinere Bildschirmgröße verwende. Ich möchte ein anderes Bild (stärker auf das Hauptmotiv fokussiert) in einer anderen Bildschirmgröße anzeigen, aber ich möchte immer noch separate Elemente desselben Bildes basierend auf dem Geräte-Pixel-Verhältnis anzeigen und die Höhe und Breite des Bilds anpassen Bild basierend auf Ansichtsfenster.

Beispielcode:

<picture>

<source media="(max-width: 20em)" srcset="images/small/space-needle.jpg 1x,
images/small/space-needle-2x.jpg 2x, images/small/space-needle-hd.jpg 3x">

<source media="(max-width: 40em)" srcset="images/medium/space-needle.jpg 1x,
images/medium/space-needle-2x.jpg 2x, images/medium/space-needle-hd.jpg 3x">

<img src="space-needle.jpg" alt="Space Needle">

</picture>
Piotr Ścigała
quelle
Positionieren Sie das Element '<Bild>' als 'absolut' oder 'fest'. Stellen Sie bei Bedarf den richtigen Z-Index + die richtige Position ein: Relativ für den Container
Piotr Ścigała
gdaniel: Ready JS-Lösung: github.com/code-mattclaffey/… Ich habe es gerade getestet und es funktioniert großartig!
Piotr Ścigała
JS-Lösung, Bild über das <picture> -Element laden und als Hintergrundbild anzeigen: github.com/code-mattclaffey/…
Piotr Ścigała
2

Wenn Sie das Foundation Framework ( https://foundation.zurb.com/ ) verwenden, können Sie das Interchange-Plugin dafür verwenden:

<div data-interchange="[assets/img/interchange/small.jpg, small], 
                       [assets/img/interchange/medium.jpg, medium], 
                       [assets/img/interchange/large.jpg, large]">
</div>

https://foundation.zurb.com/sites/docs/interchange.html#use-with-background-images

Martti Hyvönen
quelle
Danke für diesen Martti. Ich habe dies jetzt gut zusammen mit Webpacks responsive-loaderfür eine ziemlich süße Lösung verkabelt .
Fredrivett
1

Basierend auf der Antwort von @Weston habe ich eine allgemeinere jQuery-Lösung erstellt. Sie können JS und CSS einfach kopieren und einfügen und sich auf den HTML-Teil konzentrieren;)

TL; DR - Geige: https://jsfiddle.net/dpaa7oz6/

CSS

... um sicherzustellen, dass Bilder beim Laden kaum sichtbar sind

.srcSet{
  position: fixed;
  z-index: 0;
  z-index: -1;
  z-index: -100;
  /* you could probably also add visibility: hidden; */
}

JS / jQuery

Dieses Skript durchläuft alle Bilder mit srcSetKlassen- und Bindungsereignissen load, die ausgeführt werden currentSrc(oder srcnicht unterstützt werden), und legt sie als background-imageCSS an das nächstgelegene übergeordnete Element mit bgFromSrcSetKlasse weiter.

Das selbst würde nicht reichen! Daher wird auch eine Intervallprüfung für daswindow loadEreignis durchgeführt, um zu testen, ob die Ladeereignisse abgeschlossen wurden. Wenn nicht, werden sie ausgelöst. (Dasimg loadEreignis wird sehr oft nur beim erstmaligen Laden ausgelöst. Beimfolgenden Laden kann die Bildquelle aus dem Cache abgerufen werden, was dazu führt , dass das img-Ladeereignis NICHT ausgelöst wird! )

jQuery(function($){ //ON DOCUMENT READY
  var $window = $(window); //prepare window as jQuery object

  var $srcSets = $('.srcSet'); //get all images with srcSet clas
  $srcSets.each(function(){ //for each .srcSet do...
    var $currImg = $(this); //prepare current srcSet as jQuery object

    $currImg
      .load(function(){ //bind the load event
          var img = $currImg.get(0); //retrieve DOM element from $currImg

          //test currentSrc support, if not supported, use the old src
          var src = img.currentSrc ? img.currentSrc : img.src;

          //To the closest parent with bgFromSrcSet class,
          //set the final src as a background-image CSS
          $currImg.closest('.bgFromSrcSet').css('background-image', "url('"+src+"')");

          //remove processed image from the jQuery set
          //(to update $srcSets.length that is checked in the loadChecker)
          $srcSets = $srcSets.not($currImg);

          $currImg.remove(); //remove the <img ...> itself 
      })
    ;      

  });

  //window's load event is called even on following loads...
  $window.load(function(){    
    //prepare the checker
    var loadChecker = setInterval(function(){
        if( $srcSets.length > 0 ) //if there is still work to do...
            $srcSets.load(); //...do it!
        else
            clearInterval(loadChecker); //if there is nothing to do - stop the checker
    }, 150);  
  });

});

HTML

... könnte so aussehen:

<div class="bgFromSrcSet">
  <img class="srcSet"
       alt=""
       src="http://example.com/something.jpeg" 
       srcset="http://example.com/something.jpeg 5760w, http://example.com/something-300x200.jpeg 300w, http://example.com/something-768x512.jpeg 768w, http://example.com/something-1024x683.jpeg 1024w, http://example.com/something-1000x667.jpeg 1000w"
       sizes="(max-width: 2000px) 100vw, 2000px"
  >
  Something else...
</div>

Hinweis: Klasse bgFromSrcSetdarf nicht auf sich imgselbst gesetzt werden! Es kann nur auf die Elemente im imgübergeordneten DOM-Baum festgelegt werden.

jave.web
quelle