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?);
}
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
.
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.
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.
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;)
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.
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>
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
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;)
... 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; */
}
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 window
load
événement pour tester si les événements de chargement sont terminés, sinon, il les déclenche. (img
load
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);
});
});
... 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.