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

img с атрибутом srcset выглядит как отличный способ создания адаптивных изображений. Есть ли эквивалентный синтаксис, который работает в свойстве css background-image?

HTML

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

CSS

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

person Martin Algesten    schedule 07.11.2014    source источник


Ответы (8)


image-set — эквивалентная функция CSS. Мы должны добавить в спецификацию эквивалентную функциональность srcset (определение ресурсов в соответствии с их размерами).

В настоящее время реализовано во всех основных браузерах (Firefox, Chrome, Safari, Edge) с префиксом -webkit-. Safari поддерживает только дескрипторы x.

person Yoav Weiss    schedule 08.11.2014
comment
Есть ли какой-нибудь изящный запасной вариант или полифилл, поддерживающий это? - person Rachel Cantor; 07.06.2016
comment
@RachelCantor Нужен ли запасной вариант? В любом случае, только современные устройства будут иметь экраны Retina, я бы подумал? - person James Kemp; 21.07.2016
comment
Только поддержка дескрипторов x кажется бессмысленной, я имею в виду, что фоновое изображение может быть полной ширины на рабочем столе 2x 'retina' (5120 Вт), что на мобильном устройстве с 2x (720 Вт) изображение смехотворного размера для любого мобильного устройства, чтобы даже рассматривать его как веб-сайт. фон страницы. Даже использование медиа-запросов максимальной ширины для обслуживания нескольких разных размеров не так уж полезно, потому что это не максимальная ширина фонового контейнера, а максимальная ширина экрана. - person Chris Seufert; 17.11.2016
comment
Итак, если браузер не поддерживает набор изображений, что является запасным вариантом? - person O.MeeKoh; 09.02.2020

Уверен, что:

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

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

person SRing    schedule 07.11.2014
comment
В 2018 году это все еще поддерживается не всеми браузерами. caniuse.com/#search=image-set - person BadHorsie; 22.11.2018

Другой подход, который, откровенно говоря, более надежный, заключается в адаптации характеристик и параметров фоновых изображений к изображению с атрибутом 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.

person Parks    schedule 19.10.2017
comment
src-set не учитывает ширину изображения, а только ширину контейнера для object-fit: cover. Это означает, что если ваш тег img имеет ширину, скажем, 50 пикселей, но высоту 1000 пикселей, изображение, удовлетворяющее ширине 50 пикселей, загружается и растягивается, чтобы соответствовать ширине, возможно, от 240 до 1500 пикселей, чтобы отобразить только фрагмент размером 50 пикселей. - person Chris Seufert; 13.02.2018
comment
Я не знал, что object-fit: cover; существует, спасибо. С другой стороны, это был последний штрих, чтобы заставить мой код работать (я использовал тег <picture>) - person Gendrith; 04.02.2021

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

Вот скрипт: http://jsbin.com/garetikubu/edit?html,output

Использование onload и размещение JS в качестве блокирующего скрипта в <head> очень важно. Если вы поместите скрипт позже (скажем, в конце <body>), вы можете получить состояние гонки, когда img.currentSrc еще не был установлен браузером. Лучше дождаться загрузки.

Пример позволяет увидеть загружаемый исходный файл img. Вы можете легко скрыть это с помощью некоторого CSS.

person Weston    schedule 09.07.2016
comment
Интересно. Я ожидал, что при этом изображение загрузится дважды. Тем не менее, это не так. - person Perry; 30.05.2019

Вы можете использовать медиа-запросы для своих целей. Это просто:

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

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

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

person gtamborero    schedule 22.10.2017
comment
Если ваше изображение настроено на покрытие контейнера, это не учитывает, что изображение растягивается, чтобы соответствовать высоте, поле может быть в 2 или 3 раза больше ширины исходного изображения и, следовательно, будет выглядеть очень плохо по качеству. - person Chris Seufert; 13.02.2018

Аналогичное решение с использованием элемента <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>
person Piotr Ścigała    schedule 17.07.2016
comment
Позиционируйте элемент «‹изображение›» как «абсолютный» или «фиксированный». Установите правильный z-index+position: относительный для его контейнера, если это необходимо - person Piotr Ścigała; 05.03.2017
comment
gdaniel: Готовое решение JS: github.com/code-mattclaffey/ Я только что протестировал его, и он отлично работает! - person Piotr Ścigała; 12.03.2017
comment
Решение JS, загрузка изображения через элемент ‹picture› и отображение его в качестве фонового изображения: github.com/code-mattclaffey/ - person Piotr Ścigała; 03.10.2017

Если вы используете платформу 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

person Martti Hyvönen    schedule 18.02.2018
comment
Спасибо за это, Марти. Теперь я хорошо подключил это вместе с responsive-loader веб-пакета для довольно приятного решения. - person fredrivett; 28.03.2018

Основываясь на ответе @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, если не поддерживается) и помещает его как CSS background-image для ближайшего родителя с классом 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.

person jave.web    schedule 14.08.2017