Чи існує еквівалент srcset для фонового зображення css


89

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?);
}

Відповіді:


81

image-setє еквівалентною функцією CSS. Ми повинні додати еквівалентну функціональність srcset (визначаючи ресурси відповідно до їх розмірів) до специфікації.

На даний момент він реалізований лише в Safari, Chrome та Opera з -webkit-префіксом, і він підтримує лише xдескриптори.


1
чи є якийсь витончений резервний варіант чи поліфіл, що підтверджує це?
— Рейчел Кантор

5
@RachelCantor Чи потрібен резервний варіант? Як би я думав, лише сучасні пристрої мали б екрани сітківки ока?
— Джеймс Кемп,

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

14

Іншим підходом, який є відверто більш надійним, було б адаптувати характеристики та параметри фонових зображень до зображення з атрибутом 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>

Це може бути не найкращим підходом для всіх, але, я думаю, це дозволить отримати найбільш бажані результати без жодного обхідного рішення JavaScript.


1
src-set не враховує ширину зображення, лише ширину контейнера для об’єкту fit: cover. Це означає, що якщо ваш тег img закінчується, скажімо, 50px в ширину, але 1000px у висоту, зображення, яке відповідає ширині 50px, завантажується і розтягується, щоб відповідати, можливо, масштабованому від 240w до 1500px ширині, щоб відображати лише фрагмент 50px.
— Кріс Сойферт,

10

Для полізаповнення ви можете використовувати img із srcset як механізм завантаження правильного розміру зображення, а потім використовувати JS, щоб приховати його та встановити фонове зображення батьківського елемента.

Ось скрипка: http://jsbin.com/garetikubu/edit?html,output

Важливим є використання onloadта розміщення JS як сценарію блокування <head>. Якщо ви помістите скрипт пізніше (скажімо в кінці <body>), ви можете отримати умову перегонів, де img.currentSrc ще не встановлений браузером. Найкраще дочекатися його завантаження.

Приклад дозволяє побачити оригінальний img, який завантажується. Ви можете легко приховати це за допомогою CSS.


Цікаво. Я би очікував, що при цьому зображення завантажиться двічі. Однак, схоже, це не так.
— Перрі

8

Ви можете використовувати медіа-запити для своєї мети. Це легко:

.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-індекс + положення: відносне значення для його контейнера, якщо це потрібно
— Piotr Ścigała

gdaniel: Готове рішення 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 для цього:

<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


Дякую за це Марті. Зараз я це добре підключив поряд з веб-пакетами responsive-loaderдля досить солодкого рішення.
— Фредріветт

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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.