Чи існує еквівалент 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.