Esiste un equivalente srcset per l'immagine di sfondo CSS


91

imgcon srcsetattributo sembra un ottimo modo per creare immagini reattive. Esiste una sintassi equivalente che funziona nella background-imageproprietà CSS ?

HTML

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

CSS

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

Risposte:


83

image-setè la funzione CSS equivalente. Dovremmo aggiungere la funzionalità srcset equivalente (definendo le risorse in base alle loro dimensioni) alle specifiche.

Attualmente è implementato solo in Safari, Chrome e Opera con il -webkit-prefisso e supporta solo i xdescrittori.


1
c'è qualche grazioso fallback noto o un polyfill che lo supporta?
Rachel Cantor

5
@RachelCantor Sarebbe necessario un ripiego? Solo i dispositivi moderni avrebbero comunque schermi retina, avrei pensato?
James Kemp

3
Solo supportare i xdescrittori sembra inutile, intendo dire che un'immagine di sfondo potrebbe essere a tutta larghezza su un desktop 2x 'retina' (5120w), che sui dispositivi mobili a 2x (720w) un'immagine di dimensioni ridicole che qualsiasi dispositivo mobile può considerare anche come una pagina web sfondo. Anche l'utilizzo di query multimediali di larghezza massima per servire alcune dimensioni diverse non è così utile, perché non è la larghezza massima del contenitore di sfondo, la sua larghezza massima dello schermo.
Chris Seufert

1
quindi se un browser non supporta il set di immagini qual è il fallback?
O.MeeKoh,

22

Abbastanza sicuro che:

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

funziona allo stesso modo. Il browser esaminerà le immagini, vedrà quale si adatta meglio e utilizzerà quella.


2
Nel 2018 questo non è ancora supportato da tutti i browser. caniuse.com/#search=image-set
BadHorsie

17

Un altro approccio, che è francamente più robusto, sarebbe adattare le caratteristiche e le opzioni delle immagini di sfondo a un'immagine con l'attributo srcset.

Per fare ciò, imposta la larghezza dell'immagine: 100%; altezza: 100%; e object-fit: coprire o contenere.

Ecco un esempio:

.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>

Questo potrebbe non essere l'approccio migliore per tutti, ma immagino che otterrà la maggior parte dei risultati desiderati senza alcuna soluzione javascript.


1
src-set non prende in considerazione la larghezza dell'immagine, solo la larghezza del contenitore per l'adattamento all'oggetto: cover. Ciò significa che se il tuo tag img finisce per dire 50px di larghezza ma 1000px di altezza, l'immagine che soddisfa la larghezza di 50px viene caricata e allungata per adattarsi, forse scalata da 240w a 1500px di larghezza, per visualizzare solo una sezione di 50px.
Chris Seufert

11

Per un polyfill, puoi usare un img con srcset come meccanismo per scaricare la dimensione corretta dell'immagine, quindi usare JS per nasconderlo e impostare l'immagine di sfondo di un elemento genitore.

Ecco un violino: http://jsbin.com/garetikubu/edit?html,output

L'uso onloade l'inserimento di JS come script di blocco nel file <head>è importante. Se metti lo script in un secondo momento (diciamo alla fine di <body>), puoi ottenere una condizione di competizione in cui img.currentSrc non è stato ancora impostato dal browser. È meglio aspettare che venga caricato.

L'esempio ti consente di vedere l'img originale in fase di download. Puoi nasconderlo facilmente con alcuni CSS.


Interessante. Mi sarei aspettato che l'immagine venisse caricata due volte durante questa operazione. Tuttavia, non sembra.
Perry

9

Puoi utilizzare le media query per il tuo scopo. È facile come questo:

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

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

E penso che funzioni su tutti i browser che supportano le media query;)


2
Se l'immagine è impostata per coprire un contenitore, ciò non tiene conto dell'immagine allungata per adattarla all'altezza, il riquadro può essere 2 o 3 volte l'altezza della larghezza dell'immagine nativa e quindi avrà un aspetto molto scadente.
Chris Seufert

3

Soluzione simile usando l' <picture>elemento: Tutorial qui

Caso del tutorial:

Dubito che se utilizzo la stessa immagine per uno schermo di dimensioni inferiori, il soggetto principale della mia immagine potrebbe diventare di dimensioni troppo piccole. Desidero visualizzare un'immagine diversa (più focalizzata sul soggetto principale) in una dimensione dello schermo diversa, ma voglio comunque visualizzare risorse separate della stessa immagine in base al rapporto pixel-dispositivo e voglio personalizzare l'altezza e la larghezza del immagine basata su viewport.

Codice di esempio:

<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>

Posiziona l'elemento "<picture>" come "assoluto" o "fisso". Imposta z-index corretto + posizione: relativa per il suo contenitore se necessario
Piotr Ścigała

gdaniel: Soluzione JS pronta: github.com/code-mattclaffey/… L'ho appena testato e funziona benissimo!
Piotr Ścigała

Soluzione JS, caricamento dell'immagine tramite l'elemento <picture> e visualizzazione come immagine di sfondo: github.com/code-mattclaffey/…
Piotr Ścigała

2

Se utilizzi il framework Foundation ( https://foundation.zurb.com/ ), puoi utilizzare il plug-in Interchange per questo:

<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


Grazie per questo Martti. L'ho collegato bene ora insieme a webpack responsive-loaderper una soluzione piuttosto dolce.
fredrivett

1

Sulla base della risposta di @Weston , ho creato una soluzione jQuery più generale, in pratica puoi semplicemente copiare e incollare JS e CSS e concentrarti sulla parte HTML;)

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

CSS

... per garantire che le immagini siano difficilmente visibili durante il caricamento

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

JS / jQuery

Questo script esaminerà tutte le immagini che hanno un evento di srcSetclasse e bind loadche accetta currentSrc(o srcse non supportato) e lo mette come background-imageCSS al genitore più vicino con la bgFromSrcSetclasse.

Già questo non sarebbe sufficiente! Quindi mette anche un controllo dell'intervallowindow loadsull'evento per verificare se gli eventi di caricamento sono stati completati, altrimenti li attiva. (l'img loadevento è molto spesso attivato solo al primo caricamento , ai seguenti caricamenti, l'origine dell'immagine potrebbe essere recuperata dalla cache, con il risultato che l'evento img load NON viene attivato! )

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

... potrebbe assomigliare a questo:

<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>

Nota: la classe nonbgFromSrcSet deve essere impostata su se stessa! Può essere impostato solo sugli elementi nell'albero genitore DOM.imgimg

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.