Есть ли эквивалент srcset для фонового изображения css

89

imgwith srcsetattribute выглядит как отличный способ создания адаптивных изображений. Есть ли эквивалентный синтаксис, который работает в 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 (5120 Вт), что на мобильном устройстве с 2x (720 Вт) - изображение смешного размера для любого мобильного устройства, которое даже можно рассматривать как веб-страницу. задний план. Даже использование медиа-запросов максимальной ширины для обслуживания нескольких разных размеров не так полезно, потому что это не максимальная ширина контейнера фона, а максимальная ширина экрана.
Chris Seufert
1
Итак, если браузер не поддерживает набор изображений, каков запасной вариант?
O.MeeKoh
22

Совершенно уверен, что:

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

работает так же. Браузер изучит изображения, определит, какое из них лучше всего подходит, и будет использовать его.

SRing
источник
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 не принимает во внимание ширину изображения, только ширину контейнера для object-fit: cover. Это означает, что если ваш тег img заканчивается, скажем, шириной 50 пикселей, но высотой 1000 пикселей, изображение, которое удовлетворяет ширине 50 пикселей, загружается и растягивается для соответствия ширине, возможно, масштабируется от 240 Вт до 1500 пикселей, чтобы отображать только фрагмент размером 50 пикселей.
Крис Сеуферт,
11

Для полифилла вы можете использовать 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  
    }
}

И я думаю, что это работает в каждом браузере, поддерживающем медиа-запросы;)

Gtamborero
источник
2
Если ваше изображение настроено на покрытие контейнера, при этом не учитывается изображение, растягивающееся по высоте, поле может быть в 2 или 3 раза больше ширины исходного изображения и поэтому будет выглядеть очень плохого качества.
Крис Сеуферт,
3

Аналогичное решение с использованием <picture>element: Учебник здесь

Случай учебника:

Я сомневаюсь, что если я использую то же изображение для экрана меньшего размера, основной объект моего изображения может стать слишком маленьким. Я хочу отображать другое изображение (больше ориентированное на основной объект) с другим размером экрана, но я все же хочу отображать отдельные активы одного и того же изображения на основе соотношения пикселей устройства, и я хочу настроить высоту и ширину изображение на основе области просмотра.

Пример кода:

<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>
Петр cigała
источник
Позиционируйте элемент «<картинка>» как «абсолютный» или «фиксированный». При необходимости установите правильный z-index + position: relative для его контейнера
Петр cigała 05
gdaniel: Готовое решение JS: github.com/code-mattclaffey/… Я только что протестировал его, и он отлично работает!
Петр Ścigała
Решение JS, загружающее изображение через элемент <picture> и отображающее его как фоновое изображение: github.com/code-mattclaffey/…
Петр Ścigała 03
2

Если вы используете платформу Foundation ( 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для довольно приятного решения.
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

Этот сценарий просматривает все изображения, которые имеют событие srcSetclass и bind, 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>

Примечание: class неbgFromSrcSet должен быть установлен на себя! Он может быть установлен только для элементов в родительском дереве DOM.imgimg

jave.web
источник