Apakah ada srcset yang setara untuk gambar latar css

91

img dengan srcset atribut sepertinya cara yang bagus untuk melakukan gambar responsif. Apakah ada sintaks yang setara yang berfungsi di background-imageproperti css ?

HTML

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

CSS

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

Jawaban:

83

image-setadalah fitur CSS yang setara. Kita harus menambahkan fungsionalitas srcset yang setara (mendefinisikan sumber daya sesuai dengan dimensinya) ke spesifikasi.

Saat ini hanya diterapkan di Safari, Chrome dan Opera dengan -webkit-awalan, dan hanya mendukung xdeskriptor.

Yoav Weiss
sumber
1
apakah ada fallback anggun yang diketahui atau polyfill yang mendukung ini?
Rachel Cantor
5
@RachelCantor Apakah diperlukan penggantian? Bagaimanapun, hanya perangkat modern yang memiliki layar retina, menurut saya?
James Kemp
3
Hanya mendukung xdeskriptor tampaknya tidak ada gunanya, maksud saya gambar latar belakang dapat menjadi lebar penuh pada desktop 2x 'retina' (5120w), yang pada seluler dengan ukuran 2x (720w) gambar berukuran konyol untuk perangkat seluler apa pun untuk bahkan dianggap sebagai halaman web Latar Belakang. Bahkan menggunakan kueri media dengan lebar maksimal untuk menayangkan beberapa ukuran berbeda tidak terlalu membantu, karena ini bukan lebar maksimal penampung latar belakang, melainkan lebar maksimal layar.
Chris Seufert
1
jadi jika browser tidak mendukung image-set, apa fallbacknya?
O.MeeKoh
22

Cukup yakin bahwa:

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

bekerja dengan cara yang sama. Browser akan memeriksa gambar, melihat mana yang paling cocok dan akan menggunakan gambar itu.

SRing
sumber
2
Pada 2018 ini masih belum didukung oleh semua browser. caniuse.com/#search=image-set
BadHorsie
17

Pendekatan lain, yang sejujurnya lebih kuat, akan menyesuaikan karakteristik dan opsi gambar latar belakang ke gambar dengan atribut srcset.

Untuk melakukan ini, atur gambar menjadi lebar: 100%; tinggi: 100%; dan objek-fit: menutupi atau berisi.

Berikut ini contohnya:

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

Ini mungkin bukan pendekatan terbaik untuk semua orang tetapi saya membayangkan itu akan mendapatkan hasil yang paling diinginkan tanpa solusi javascript.

Taman
sumber
1
src-set tidak memperhitungkan lebar gambar, hanya lebar container untuk object-fit: cover. Ini berarti bahwa jika tag img Anda berakhir dengan lebar 50px tetapi tinggi 1000px, gambar yang memenuhi lebar 50px akan dimuat dan direntangkan agar pas, mungkin diskalakan dari lebar 240w hingga 1500px, untuk menampilkan hanya potongan 50px.
Chris Seufert
11

Untuk polyfill, Anda dapat menggunakan img dengan srcset sebagai mekanisme untuk mengunduh ukuran gambar yang benar, lalu menggunakan JS untuk menyembunyikannya dan menyetel gambar latar belakang elemen induk.

Ini biola: http://jsbin.com/garetikubu/edit?html,output

Penting untuk menggunakan onloaddan menempatkan JS sebagai skrip pemblokiran <head>. Jika Anda meletakkan skrip nanti (katakanlah di akhir <body>), Anda bisa mendapatkan kondisi balapan di mana img.currentSrc belum disetel oleh browser. Yang terbaik adalah menunggu untuk dimuat.

Contohnya memungkinkan Anda untuk melihat img asli sedang diunduh. Anda dapat dengan mudah menyembunyikannya dengan beberapa CSS.

Weston
sumber
Menarik. Saya berharap gambar dimuat dua kali saat melakukan ini. Namun, tampaknya tidak.
Perry
9

Anda dapat menggunakan kueri media untuk tujuan Anda. Semudah ini:

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

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

Dan menurut saya ini berfungsi pada setiap browser yang mendukung kueri media;)

gtamborero
sumber
2
Jika gambar Anda disetel untuk menutupi wadah, ini tidak memperhitungkan gambar yang diregangkan agar pas dengan tingginya, kotak tersebut mungkin 2 atau 3 kali tinggi lebar gambar asli dan akan terlihat sangat buruk dalam kualitas.
Chris Seufert
3

Solusi serupa menggunakan <picture>elemen: Tutorial di sini

Kasus tutorial:

Saya ragu jika saya menggunakan gambar yang sama untuk ukuran layar yang lebih kecil, subjek utama gambar saya mungkin ukurannya menjadi terlalu kecil. Saya ingin menampilkan gambar yang berbeda (lebih fokus pada subjek utama) dalam ukuran layar yang berbeda, tetapi saya masih ingin menampilkan aset terpisah dari gambar yang sama berdasarkan rasio piksel perangkat, dan saya ingin menyesuaikan tinggi dan lebar gambar berdasarkan viewport.

Kode contoh:

<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
sumber
Posisikan elemen '<picture>' sebagai 'absolute' atau 'fixed'. Setel posisi + indeks-z yang benar: relatif untuk penampungnya jika diperlukan
Piotr Ścigała
gdaniel: Solusi JS Siap Pakai: github.com/code-mattclaffey/… Saya baru saja mengujinya dan berhasil!
Piotr Ścigała
Solusi JS, memuat gambar melalui elemen <picture> dan menampilkannya sebagai gambar latar belakang: github.com/code-mattclaffey/…
Piotr Ścigała
2

Jika Anda menggunakan framework Foundation ( https://foundation.zurb.com/ ), Anda dapat menggunakan plugin Interchange untuk itu:

<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
sumber
Terima kasih untuk Martti ini. Saya telah memasang kabel ini dengan baik sekarang di samping webpack responsive-loaderuntuk solusi yang cukup manis.
fredrivett
1

Berdasarkan jawaban @Weston , saya telah membuat solusi jQuery yang lebih umum, pada dasarnya Anda cukup menyalin & menempelkan JS dan CSS dan fokus pada bagian HTML;)

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

CSS

... untuk memastikan gambar hampir tidak terlihat saat memuat

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

JS / jQuery

Skrip ini akan memeriksa semua gambar yang memiliki srcSetclass dan loadevent bind yang mengambil currentSrc(atau srcjika tidak didukung) dan meletakkannya sebagai background-imageCSS ke induk terdekat dengan bgFromSrcSetkelas.

Itu saja tidak akan cukup! Jadi itu juga menempatkan pemeriksa interval padawindow loadacara untuk menguji apakah peristiwa beban telah selesai, jika tidak, itu memicunya. (img loadPeristiwa sangat sering terpicu hanya pada pemuatan pertama kali , pada pemuatan berikutnya, sumber gambar dapat diambil dari cache, sehingga peristiwa pemuatan img TIDAK diaktifkan! )

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

... bisa terlihat seperti ini:

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

Catatan: class bgFromSrcSetharus tidak diatur ke imgitu sendiri! Ini hanya dapat disetel ke elemen di imgpohon induk DOM.

jave.web
sumber