Fallback background-image if default doesn't e

2019-06-14 22:00发布

I want to set an image as a background, however the image name might be either bg.png or bg.jpg.

Is there any non-javascript way to create a fallback to an alternative image if the default background doesn't exist?

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

3条回答
迷人小祖宗
2楼-- · 2019-06-14 22:03

To specify multiple possible backgrounds, you could do:

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

This will set the background to bg.png if it exists. If it doesn't exist, it will be set to bg.jpg. If none of those images exist, the background will be set to the static green color.

Note that it will prioritize whatever image is specified first. So if both images exist, it will choose the bg.png over the bg.jpg.

Check out the demo here. Test it by breaking any of the image urls'.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-06-14 22:03

I wanted to have a solution that doesn't load the images twice. For example CDN with a fallback is not very good if it always loads the original images also. So I ended up writing a Javascript to manipulate the loaded 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楼-- · 2019-06-14 22:27

You can use multiple backgrounds if there is no transparency involved and they occupy all available space or have the same size:

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>

If the first doesn't exit, the second will be displayed.

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

查看更多
登录 后发表回答