¿Existe un equivalente srcset para la imagen de fondo css?

89

imgcon srcsetatributo parece una excelente manera de hacer imágenes receptivas. ¿Existe una sintaxis equivalente que funcione en la background-imagepropiedad css ?

HTML

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

CSS

.mycontainer {
    background: url(?something goes here?);
}
Martín Algesten
fuente

Respuestas:

81

image-setes la característica CSS equivalente. Deberíamos agregar una funcionalidad srcset equivalente (definiendo recursos según sus dimensiones) a la especificación.

Actualmente solo se implementa en Safari, Chrome y Opera con el -webkit-prefijo, y solo admite los xdescriptores.

Yoav Weiss
fuente
1
¿Se conoce alguna alternativa elegante o un polyfill que respalde esto?
Rachel Cantor
5
@RachelCantor ¿Sería necesario un respaldo? De todos modos, solo los dispositivos modernos tendrían pantallas de retina, ¿habría pensado?
James Kemp
3
Solo admitir los xdescriptores parece inútil, me refiero a que una imagen de fondo podría tener el ancho completo en un escritorio de 2x 'retina' (5120w), que en un dispositivo móvil a 2x (720w) una imagen de tamaño ridículo para que cualquier dispositivo móvil la considere incluso como una página web. antecedentes. Incluso el uso de consultas de medios de ancho máximo para publicar algunos tamaños diferentes no es tan útil, porque no es el ancho máximo del contenedor de fondo, su ancho máximo de la pantalla.
Chris Seufert
1
Entonces, si un navegador no admite el conjunto de imágenes, ¿cuál es la alternativa?
O.MeeKoh
22

Estoy bastante seguro de que:

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

funciona de la misma manera. El navegador examinará las imágenes, verá cuál encaja mejor y utilizará esa.

SRing
fuente
2
En 2018, esto todavía no es compatible con todos los navegadores. caniuse.com/#search=image-set
BadHorsie
14

Otro enfoque, francamente más sólido, sería adaptar las características y opciones de las imágenes de fondo a una imagen con el atributo srcset.

Para hacer esto, configure la imagen en ancho: 100%; altura: 100%; y ajuste de objeto: cubrir o contener.

Aquí hay un ejemplo:

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

Puede que este no sea el mejor enfoque para todos, pero imagino que obtendrá la mayoría de los resultados deseados sin ninguna solución alternativa de JavaScript.

Parques
fuente
1
src-set no tiene en cuenta el ancho de la imagen, solo el ancho del contenedor para object-fit: cover. Esto significa que si su etiqueta img termina digamos 50px de ancho pero 1000px de alto, la imagen que satisface el ancho de 50px se carga y se estira para ajustarse, tal vez escalada de 240w a 1500px de ancho, para mostrar solo un corte de 50px.
Chris Seufert
11

Para un polyfill, puede usar un img con srcset como mecanismo para descargar el tamaño de imagen correcto, luego usar JS para ocultarlo y establecer la imagen de fondo de un elemento principal.

Aquí hay un violín: http://jsbin.com/garetikubu/edit?html,output

El uso onloady la colocación de JS como un script de bloqueo en el <head>es importante. Si coloca el script más tarde (por ejemplo, al final de <body>), puede obtener una condición de carrera en la que el navegador aún no ha establecido img.currentSrc. Es mejor esperar a que se cargue.

El ejemplo le permite ver la imagen original descargada. Puede ocultarlo fácilmente con algo de CSS.

Weston
fuente
Interesante. Hubiera esperado que la imagen se cargara dos veces al hacer esto. Sin embargo, no parece ser así.
Perry
8

Puede utilizar consultas de medios para su propósito. Es tan fácil como esto:

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

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

Y creo que funciona en todos los navegadores que admiten consultas de medios;)

gtamborero
fuente
2
Si su imagen está configurada para cubrir un contenedor, esto no tiene en cuenta que la imagen se estira para ajustarse a la altura, el cuadro puede ser 2 o 3 veces la altura del ancho de la imagen original y, por lo tanto, se verá muy de mala calidad.
Chris Seufert
3

Solución similar usando el <picture>elemento: Tutorial aquí

Caso del tutorial:

Dudo que si utilizo la misma imagen para un tamaño de pantalla más pequeño, el sujeto principal de mi imagen puede volverse demasiado pequeño. Quiero mostrar una imagen diferente (más enfocada en el sujeto principal) en un tamaño de pantalla diferente, pero aún quiero mostrar activos separados de la misma imagen en función de la proporción de píxeles por dispositivo, y quiero personalizar la altura y el ancho de la imagen basada en la ventana gráfica.

Código de ejemplo:

<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
fuente
Coloque el elemento '<imagen>' como 'absoluto' o 'fijo'. Establezca la posición correcta del índice z +: relativa para su contenedor si es necesario
Piotr Ścigała
gdaniel: Solución JS lista: github.com/code-mattclaffey/ ... ¡ Lo acabo de probar y está funcionando muy bien!
Piotr Ścigała
Solución JS, cargando la imagen a través del elemento <picture> y mostrándola como una imagen de fondo: github.com/code-mattclaffey/…
Piotr Ścigała
2

Si está utilizando Foundation framework ( https://foundation.zurb.com/ ), puede usar el complemento Interchange para eso:

<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
fuente
Gracias por esto Martti. Tengo esto bien conectado ahora junto con el paquete web responsive-loaderpara una solución bastante dulce.
fredrivett
1

Basado en @Weston la respuesta de , he creado una solución jQuery más general, básicamente puedes copiar y pegar JS y CSS y concentrarte en la parte HTML;)

TL; DR - violín: https://jsfiddle.net/dpaa7oz6/

CSS

... para garantizar que las imágenes sean apenas visibles durante la carga

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

JS / jQuery

Este script pasará por todas las imágenes que tienen srcSetclase y vinculará el loadevento que toma currentSrc(o srcsi no es compatible) y lo pondrá como background-imageCSS al padre más cercano con bgFromSrcSetclase.

¡Eso en sí mismo no sería suficiente! Por lo tanto, también coloca un verificador de intervalo en elwindow loadevento para probar si los eventos de carga se han completado, si no, los activa. (Elimg loadevento a menudo se activa solo en la primera carga , en las siguientes cargas, la fuente de la imagen podría recuperarse de la caché, ¡ lo que hace que el evento de carga de img NO se active! )

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

... podría verse así:

<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 clase bgFromSrcSetdebe no ajustarse a la imgmisma! Solo se puede establecer en los elementos del imgárbol padre DOM.

jave.web
fuente