web-dev-qa-db-fra.com

Existe-t-il un équivalent srcset pour l'image de fond css?

img avec l'attribut srcset semble être un excellent moyen de créer des images réactives. Existe-t-il une syntaxe équivalente qui fonctionne dans css background-image propriété?

HTML

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

CSS

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

image-set est la fonctionnalité CSS équivalente. Nous devrions ajouter une fonctionnalité srcset équivalente (définition des ressources en fonction de leurs dimensions) à la spécification.

Actuellement, il n'est implémenté que dans Safari, Chrome et Opera avec le -webkit- préfixe, et il ne supporte que les descripteurs x.

72
Yoav Weiss

Je suis sûr que

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

fonctionne de la même manière. Le navigateur examinera les images, déterminera celle qui convient le mieux et l'utilisera.

20
SRing

Pour un remplissage multiple, vous pouvez utiliser un img avec srcset comme mécanisme pour télécharger la taille d'image correcte, puis utiliser JS pour le masquer et définir l'image d'arrière-plan d'un élément parent.

Voici un violon: http://jsbin.com/garetikubu/edit?html,output

L'utilisation de onload et l'insertion de JS en tant que script de blocage dans le <head> est important. Si vous mettez le script plus tard (disons à la fin de <body>), vous pouvez obtenir une situation de concurrence critique dans laquelle img.currentSrc n'a pas encore été défini par le navigateur. Il est préférable d'attendre qu'il soit chargé.

L'exemple vous permet de voir l'original img en cours de téléchargement. Vous pouvez facilement le cacher avec certains CSS.

9
Weston

Vous pouvez utiliser les requêtes des médias pour votre objectif. C'est simple comme ça:

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

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

Et je pense que cela fonctionne sur tous les navigateurs prenant en charge les requêtes multimédia;)

5
gtamborero

Une autre approche, qui est franchement plus robuste, consisterait à adapter les caractéristiques et les options des images d’arrière-plan à une image dotée de l’attribut srcset.

Pour ce faire, définissez l'image sur largeur: 100%; hauteur: 100%; et object-fit: couvrir ou contenir.

Voici un exemple:

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

<img class="psuedo-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>

Ce n'est peut-être pas la meilleure approche pour tout le monde, mais j'imagine qu'il obtiendra la plupart des résultats souhaités sans solution de contournement en javascript.

5
Parks

Solution similaire utilisant <picture> _ element: Tutorial here

Cas du tutoriel:

Je doute que si j'utilise la même image pour une taille d'écran plus petite, le sujet principal de mon image devienne trop petit. Je souhaite afficher une image différente (plus ciblée sur le sujet principal) dans une taille d'écran différente, mais je souhaite tout de même afficher des ressources distinctes de la même image en fonction du rapport entre pixels, et je souhaite personnaliser la hauteur et la largeur de l'écran. image basée sur la fenêtre.

Exemple de code:

<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>
3
Piotr Ścigała

Si vous utilisez le framework Foundation ( https://foundation.zurb.com/ ), vous pouvez utiliser le plug-in Interchange pour cela:

<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

2
Martti Hyvönen

Basé sur la réponse de @ Weston , j'ai construit une solution jQuery plus générale, vous pouvez simplement copier/coller les fichiers JS et CSS et vous concentrer sur la partie HTML;)

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

CSS

... pour vous assurer que les images seront à peine visibles lors du chargement

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

JS/jQuery

Ce script parcourt toutes les images ayant la classe srcSet et lie l'événement load qui prend currentSrc (ou src s'il n'est pas pris en charge) et le met comme un background-image CSS au parent le plus proche avec la classe bgFromSrcSet.

Cela en soi ne serait pas suffisant ! Donc, il met également un vérificateur d'intervalle sur windowload événement pour tester si les événements de chargement sont terminés, sinon, il les déclenche. (imgload l'événement est très souvent déclencheur uniquement lors du premier chargement . Lors du chargement suivant, l'image source pourrait être récupéré du cache, entraînant un événement de chargement img [~ # ~] et non [~ # ~] étant déclenché ! =)

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

... pourrait ressembler à ceci:

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

Remarque: la classe bgFromSrcSet doit ne pas être définie sur le img lui-même! Il ne peut être défini que sur les éléments de l'arborescence parent img DOM.

2
jave.web