Резервное фоновое изображение, если по умолчанию не существует

Я хочу установить изображение в качестве фона, однако имя изображения может быть либо bg.png, либо bg.jpg.

Есть ли какой-либо способ, отличный от javascript, для создания резервной копии альтернативного изображения, если фон по умолчанию не существует?

body{
    background: url(bg.png);
    background-size: 100% 100%;
    width: 100vw;
    height: 100vh;
    margin: 0;
}

Ответ 1

Вы можете использовать несколько фонов, если нет прозрачности, и они занимают все доступное пространство или имеют одинаковый размер:

div{   
     background-image: url('http://placehold.it/1000x1000'), url('http://placehold.it/500x500');
     background-repeat:no-repeat;
     background-size: 100%;
     height:200px;
     width:200px;
}
<div></div>

Ответ 2

Чтобы указать несколько возможных фонов, вы можете сделать:

  background-color: green;
  background-image: url('bg.png'), url('bg.jpg');

Это установит фон в bg.png если он существует. Если он не существует, он будет установлен в bg.jpg. Если ни одно из этих изображений не существует, фон будет установлен на статический green цвет.

Обратите внимание, что это будет определять приоритет любого изображения, указанного первым. Поэтому, если оба изображения существуют, он выберет bg.png bg.jpg.

Проверьте демо здесь. Проверьте это, взломав любой URL-адрес изображения.

Ответ 3

Я хотел иметь решение, которое не загружает изображения дважды. Например, CDN с запасным вариантом не очень хорош, если он всегда загружает также оригинальные изображения. В итоге я написал Javascript для управления загруженным CSS DOM.

var cdn = "https://mycdn.net/"; // Original location or thing to find
var localImageToCssPath = "../"; // Replacement, Css are in /css/ folder.

function replaceStyleRule(allRules){
  var rulesCount = allRules.length;

  for (var i=0; i < rulesCount; i++) 
  {
    if(allRules[i].style !== undefined && allRules[i].style !== null &&
        allRules[i].style.backgroundImage !== undefined &&
        allRules[i].style.backgroundImage !== null &&
        allRules[i].style.backgroundImage !== "" &&
        allRules[i].style.backgroundImage !== "none" &&
        allRules[i].style.backgroundImage.indexOf(cdn) > -1
            )
      {
        var tmp = allRules[i].style.backgroundImage.replace(cdn, localImageToCssPath);
        //console.log(tmp);
        allRules[i].style.backgroundImage = tmp;
      }
      if(allRules[i].cssRules !== undefined && allRules[i].cssRules !== null){
        replaceStyleRule(allRules[i].cssRules);
      }

  }
}
function fixBgImages(){
  var allSheets = document.styleSheets;
  if(allSheets===undefined || allSheets===null){
    return;
  }
  var sheetsCount = allSheets.length;
  for (var j=0; j < sheetsCount; j++) 
  {
    var allRules = null;
    try{
        allRules = allSheets[j].cssRules;
    } catch(e){
        // Access can be denied
    }
    if(allRules!==undefined && allRules!==null){
        replaceStyleRule(allRules);
    }
  }
}

// use fixBgImages() in e.g. onError

Ответ 4

Хотя в этом решении используется JS, оно загрузит первое изображение с помощью CSS и только использует JS для загрузки запасного изображения, если основное изображение не удалось загрузить.

Сначала установите основное изображение с помощью CSS как обычно, например:

.myImage {
    background-image = "main-image.png";
}

И добавьте следующий JS, который будет действовать только в случае сбоя при загрузке основного изображения (в противном случае резервное изображение никогда не будет загружено).

var img = document.createElement("img");
img.onerror = function() {
    var style = document.createElement('style');
    style.innerHTML = '.myImage { background-image = url("http://fallback_image.png"); }';
    document.head.appendChild(style);
}
img.src = "main_image.png";

Обратите внимание, что вы можете добавить несколько правил в блок CSS, добавленный с помощью javascript, например, если вам нужно сделать это с несколькими элементами.