มี srcset เทียบเท่ากับภาพพื้นหลัง css หรือไม่


91

imgด้วยsrcsetแอตทริบิวต์ดูเหมือนเป็นวิธีที่ยอดเยี่ยมในการทำรูปภาพที่ตอบสนอง มีไวยากรณ์เทียบเท่าที่ทำงานในbackground-imageคุณสมบัติcss หรือไม่

HTML

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

CSS

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

คำตอบ:


83

image-setเป็นคุณสมบัติ CSS ที่เทียบเท่า เราควรเพิ่มฟังก์ชัน srcset ที่เทียบเท่า (การกำหนดทรัพยากรตามมิติข้อมูล) ให้กับข้อมูลจำเพาะ

ขณะนี้ใช้งานได้เฉพาะใน Safari, Chrome และ Opera ที่มี-webkit-คำนำหน้าและรองรับเฉพาะตัวxอธิบายเท่านั้น


1
มีทางเลือกที่สง่างามเป็นที่รู้จักหรือมี polyfill ที่สนับสนุนสิ่งนี้หรือไม่?
Rachel Cantor

5
@RachelCantor ทางเลือกที่จำเป็นหรือไม่? อุปกรณ์ที่ทันสมัยเท่านั้นที่จะมีหน้าจอเรติน่าฉันเคยคิดไหม?
James Kemp

3
การสนับสนุนxคำอธิบายเท่านั้นที่ดูเหมือนไม่มีจุดหมายฉันหมายถึงภาพพื้นหลังอาจมีความกว้างเต็มบนเดสก์ท็อป 2x 'เรตินา' (5120w) ซึ่งบนมือถือที่ 2x (720w) เป็นภาพที่ไร้สาระสำหรับอุปกรณ์เคลื่อนที่ใด ๆ ที่จะพิจารณาเป็นหน้าเว็บ พื้นหลัง. แม้แต่การใช้ข้อความค้นหาสื่อที่มีความกว้างสูงสุดเพื่อแสดงขนาดที่แตกต่างกันเล็กน้อยก็ไม่ได้ช่วยได้เต็มที่เพราะคอนเทนเนอร์พื้นหลังไม่ใช่ความกว้างสูงสุด แต่เป็นความกว้างสูงสุดของหน้าจอ
Chris Seufert

1
ดังนั้นหากเบราว์เซอร์ไม่รองรับการตั้งค่ารูปภาพทางเลือกคืออะไร?
O.MeeKoh

22

ค่อนข้างแน่ใจว่า:

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

ทำงานในลักษณะเดียวกัน เบราว์เซอร์จะตรวจสอบภาพดูว่าภาพใดเหมาะสมที่สุดและจะใช้ภาพนั้น


2
ในปี 2018 ยังไม่รองรับเบราว์เซอร์ทั้งหมด caniuse.com/#search=image-set
BadHorsie

17

อีกวิธีหนึ่งซึ่งค่อนข้างตรงไปตรงมามากกว่าคือการปรับลักษณะและตัวเลือกของภาพพื้นหลังให้เป็นภาพที่มีแอตทริบิวต์ srcset

ในการดำเนินการนี้ให้ตั้งค่าภาพให้มีความกว้าง: 100%; ความสูง: 100%; และพอดีกับวัตถุ: ครอบคลุมหรือมี

นี่คือตัวอย่าง:

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

นี่อาจไม่ใช่แนวทางที่ดีที่สุดสำหรับทุกคน แต่ฉันคิดว่ามันจะได้ผลลัพธ์ที่ต้องการมากที่สุดโดยไม่ต้องใช้วิธีแก้ปัญหาด้วยจาวาสคริปต์


1
src-set ไม่ได้คำนึงถึงความกว้างของรูปภาพเพียงความกว้างของคอนเทนเนอร์สำหรับ object-fit: cover ซึ่งหมายความว่าหากแท็ก img ของคุณลงท้ายด้วยความกว้าง 50px แต่สูง 1000px รูปภาพที่มีความกว้าง 50px จะถูกโหลดและขยายให้พอดีโดยอาจปรับขนาดจากความกว้าง 240w ถึง 1500px เพื่อแสดงเฉพาะส่วน 50px
Chris Seufert

11

สำหรับ polyfill คุณสามารถใช้ img กับ srcset เป็นกลไกในการดาวน์โหลดขนาดภาพที่ถูกต้องจากนั้นใช้ JS เพื่อซ่อนและตั้งค่าภาพพื้นหลังขององค์ประกอบหลัก

นี่คือซอ: http://jsbin.com/garetikubu/edit?html,output

การใช้onloadและการวาง JS เป็นสคริปต์การบล็อก<head>เป็นสิ่งสำคัญ หากคุณใส่สคริปต์ในภายหลัง (พูดตอนท้าย<body>) คุณจะได้รับเงื่อนไขการแข่งขันที่เบราว์เซอร์ยังไม่ได้ตั้งค่า img.currentSrc ดีที่สุดคือรอให้โหลด

ตัวอย่างช่วยให้คุณเห็น img ต้นฉบับที่กำลังดาวน์โหลด คุณสามารถซ่อนมันได้อย่างง่ายดายด้วย CSS บางอย่าง


น่าสนใจ. ฉันคาดว่ารูปภาพจะโหลดสองครั้งเมื่อทำสิ่งนี้ อย่างไรก็ตามไม่ปรากฏว่า
Perry

9

คุณสามารถใช้แบบสอบถามสื่อตามวัตถุประสงค์ของคุณ ทำได้ง่ายๆดังนี้:

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

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

และฉันคิดว่ามันใช้ได้กับทุกเบราว์เซอร์ที่รองรับการสืบค้นสื่อ;)


2
หากรูปภาพของคุณถูกตั้งค่าให้ครอบคลุมคอนเทนเนอร์สิ่งนี้ไม่ได้คำนึงถึงการยืดรูปภาพเพื่อให้พอดีกับความสูงกล่องอาจมีความสูง 2 หรือ 3 เท่าของความกว้างของรูปภาพดั้งเดิมดังนั้นจึงมีคุณภาพที่ไม่ดี
Chris Seufert

3

วิธีแก้ปัญหาที่คล้ายกันโดยใช้<picture>องค์ประกอบ: บทช่วยสอนที่นี่

กรณีของบทช่วยสอน:

ฉันสงสัยว่าถ้าฉันใช้ภาพเดียวกันสำหรับขนาดหน้าจอที่เล็กลงตัวแบบหลักของรูปภาพของฉันอาจมีขนาดเล็กเกินไป ฉันต้องการแสดงภาพที่แตกต่างออกไป (เน้นที่วัตถุหลักมากกว่า) ในขนาดหน้าจอที่แตกต่างกัน แต่ฉันยังต้องการแสดงเนื้อหาที่แยกจากกันของรูปภาพเดียวกันตามอัตราส่วนพิกเซลอุปกรณ์และฉันต้องการปรับแต่งความสูงและความกว้างของ ภาพตามวิวพอร์ต

รหัสตัวอย่าง:

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

จัดตำแหน่งองค์ประกอบ "<picture>" เป็น "สัมบูรณ์" หรือ "คงที่" ตั้งค่า z-index + ตำแหน่งที่ถูกต้อง: สัมพันธ์กับคอนเทนเนอร์หากจำเป็น
Piotr Ścigała

gdaniel: โซลูชัน Ready JS: github.com/code-mattclaffey/…ฉันเพิ่งทดสอบและใช้งานได้ดี!
Piotr Ścigała

โซลูชัน JS โหลดภาพผ่านองค์ประกอบ <picture> และแสดงเป็นภาพพื้นหลัง: github.com/code-mattclaffey/…
Piotr Ścigała

2

หากคุณใช้ Foundation framework ( https://foundation.zurb.com/ ) คุณสามารถใช้ Interchange plugin เพื่อ:

<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 นี้ ตอนนี้ฉันได้รับการเชื่อมต่ออย่างดีพร้อมกับ webpack responsive-loaderสำหรับโซลูชันที่น่ารัก
fredrivett

1

จากคำตอบของ@Westonฉันได้สร้างโซลูชัน jQuery ทั่วไปมากขึ้นโดยพื้นฐานแล้วคุณสามารถคัดลอกและวาง JS และ CSS และมุ่งเน้นไปที่ส่วน HTML;)

TL; DR - ซอ: https://jsfiddle.net/dpaa7oz6/

CSS

... เพื่อให้แน่ใจว่าภาพจะมองไม่เห็นในขณะโหลด

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

JS / jQuery

สคริปต์นี้จะส่งผ่านรูปภาพทั้งหมดที่มีsrcSetคลาสและloadเหตุการณ์การโยงที่ใช้เวลาcurrentSrc(หรือsrcหากไม่รองรับ) และวางเป็นbackground-imageCSS ให้กับพาเรนต์ที่ใกล้เคียงที่สุดกับbgFromSrcSetคลาส

แค่นั้นเองคงไม่พอ! ดังนั้นมันยังทำให้ตัวตรวจสอบช่วงเวลาในwindow loadเหตุการณ์เพื่อทดสอบว่าเหตุการณ์การโหลดเสร็จสมบูรณ์หรือไม่หากไม่เป็นเช่นนั้นมันจะทริกเกอร์เหตุการณ์เหล่านั้น (img loadเหตุการณ์มากมักจะเรียกเฉพาะในการโหลดครั้งแรกเมื่อวันที่ต่อไปนี้โหลดที่มาของภาพอาจจะดึงมาจากแคชที่เกิดขึ้นในเหตุการณ์ img โหลดไม่ถูกไล่ออก! )

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

... อาจมีลักษณะดังนี้:

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

หมายเหตุ:ชั้นเรียนbgFromSrcSetจะต้องไม่ถูกตั้งค่าเป็นimgตัวเอง! สามารถตั้งค่าเป็นองค์ประกอบในimgแผนผังแม่ของ DOM เท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.