14

What's the best way to find all of the background images on a given page using javascript?

The ideal end result would be an array of all of the url's.

AutomaticDrone
  • 173
  • 2
  • 6
  • 8
    jQuery enthusiasts, notice the tag 'no-framework'. –  Mar 12 '10 at 04:47
  • The main problem is that the images and the classes can be defined inside the CSS class. The images will be downloaded separately. You can however create a HttpHandler that will handle all the images. For that you will need to use the .NET framework. – azamsharp Mar 12 '10 at 04:59
  • The answer (second snippet) from this question is the fastest and shortest solution I found: https://stackoverflow.com/a/4952411/313501 – Philipp May 12 '21 at 16:37

8 Answers8

12

//alert(getallBgimages())

function getallBgimages(){
 var url, B= [], A= document.getElementsByTagName('*');
 A= B.slice.call(A, 0, A.length);
 while(A.length){
  url= document.deepCss(A.shift(),'background-image');
  if(url) url=/url\(['"]?([^")]+)/.exec(url) || [];
  url= url[1];
  if(url && B.indexOf(url)== -1) B[B.length]= url;
 }
 return B;
}

document.deepCss= function(who, css){
 if(!who || !who.style) return '';
 var sty= css.replace(/\-([a-z])/g, function(a, b){
  return b.toUpperCase();
 });
 if(who.currentStyle){
  return who.style[sty] || who.currentStyle[sty] || '';
 }
 var dv= document.defaultView || window;
 return who.style[sty] || 
 dv.getComputedStyle(who,"").getPropertyValue(css) || '';
}

Array.prototype.indexOf= Array.prototype.indexOf || 
 function(what, index){
 index= index || 0;
 var L= this.length;
 while(index< L){
  if(this[index]=== what) return index;
  ++index;
 }
 return -1;
}
kennebec
  • 102,654
  • 32
  • 106
  • 127
  • For the 6th line, shouldn't it be [^")'] instead of [^")] so you can match urls that end with a single quote? – cheng Jul 18 '17 at 21:52
6

Without using jQuery, you can do:

var elementNames = ["div", "body", "td"] // Put all the tags you want bg images for here
var allBackgroundURLs = new Array();
elementNames.forEach( function(tagName) {
     var tags = document.getElementsByTagName(tagName);
     var numTags = tags.length;
     for (var i = 0; i < numTags; i++) {
         tag = tags[i];
         if (tag.style.background.match("url")) {
             var bg = tag.style.background;
             allBackgroundURLs.push(bg.substr(bg.indexOf("url") + 4, bg.lastIndexOf(")") - (bg.indexOf("url") + 4) ) );
         }
     }
});
clee
  • 10,943
  • 6
  • 36
  • 28
  • 1
    In Chrome I actually find it in `tag.style.backgroundImage`, but otherwise works like a charm. – lapo May 13 '17 at 04:17
2

One of the way is to look through all document object and get there styles. Then test style.background attribute on "url(" string and if it matches then get path between "url(" and ")" and put it into array. Algorithm for JS. Try to do it yourself. Will find troubles - came with code.

Artsiom Anisimau
  • 1,139
  • 3
  • 11
  • 26
1

Here's a way to check what background urls there are in the styles on the page (look Ma, no jQuery):

window.npup = (function (doc) {
  var sheets = doc.styleSheets;
  var hash = {}, sheet, rules, rule, url, match;
  // loop the stylesheets
  for (var sheetIdx=0, sheetsLen=sheets.length; sheetIdx<sheetsLen; ++sheetIdx) {
    sheet = sheets[sheetIdx];
    // ie or w3c stylee rules property?
    rules = sheet.rules ? sheet.rules : sheet.cssRules;
    // loop the rules
    for (var ruleIdx=0, rulesLen=rules.length; ruleIdx<rulesLen; ++ruleIdx) {
      rule = rules[ruleIdx];
      if (rule.selectorText && rule.style.cssText) {
        // check if there's a style setting we're interested in..
        if (rule.style.cssText.match(/background/)) {
          // ..and if it has an url in it, put it in the hash
          match = /url\(([^)]*)\)/.exec(rule.style.cssText);
          if (match) {hash[match[1]] = true;}
        }
      }
    }
  }
  // return an array of unique urls
  var urls = [];
  for (url in hash) {urls.push(url);}
  // export a getter for what we found
  return {
    getBackgroundUrls: function () { return urls;}
  };
})(document); // submit reference to the document of interest

With this on the page you can get an array of urls with npup.getBackgroundUrls(); I did some (superfluos?) commenting in the code that explains how it goes about. It doesn't grab inlined styles, but I think that was no problem for you? Styles in external sheets and in <style> tags on the page are scavenged.

The routine is easy to modify if you would like to keep a count, or keep associations to the actual rules that an url was found in etc.

npup
  • 2,531
  • 1
  • 17
  • 22
  • 1
    This is working great for me. Especially useful for preloading images that are attached to elements that are not in the DOM yet. Thanks for posting! – donut Sep 30 '11 at 15:55
  • 1
    Updated this code for better cross-browser support and so that it doesn't fire unless called first: https://gist.github.com/1293825 An important thing to note is that this method probably will not work for stylesheets on different domains and ports than the current page. – donut Oct 17 '11 at 21:10
  • 1
    I've further improved my version of this function to better handle IE 7 & 8. They convert CSS properties to uppercase and this function wasn't doing a case-insensitive search. The updated version is at the same URL: https://gist.github.com/1293825 – donut Oct 17 '11 at 23:18
  • Using `styleSheets` is a little tricky, because you need to manually check **for media-queries** and also handle **CORS restrictions** when CSS files are loaded from other servers (such as google maps styles) – Philipp May 12 '21 at 16:37
1

get collection elements which have inline background styles

document.querySelectorAll('[style*="background"]')
arkan4ik92
  • 71
  • 5
0

This is a complicated problem. The reason is that the background-image can be applied to the element by using a separate CSS file. This way parsing all the objects in the DOM and checking for their background-image will not work.

One of the ways I can see is to create a simple HttpHandler which will work on all the type of images. When images are referenced inside the CSS file they are downloaded as a separate entity. This means HttpHandler will be able to capture the type of the image and then execute on it.

Maybe a server side solution is the best way to go on this one!

azamsharp
  • 19,710
  • 36
  • 144
  • 222
0

I needed this function, but they were all too heavy unfortunately. So thinking about it, here is my solution, if it can help.

function getAllBgInHtml()
{
    return document.body.innerHTML.match(/background-image.+?\((.+?)\)/gi).map(function(e){ return ((e.match(/background-image.+?\((.+?)\)/i) || [])[1] || '').replace(/&quot;|"/g,'') });
}

Does not work for background image in external stylesheet.

Liberateur
  • 1,337
  • 1
  • 14
  • 33
0

[...new Set(Array.from(document.querySelectorAll('div')).map(x => window.getComputedStyle(x).getPropertyValue('background-image').split(/[^4],\s*/)).flat())].map(x=>x.replace(/^\s*url\(["']([^"']+)["']\)?\s*$/, '$1'))

  • New Set: Unique values
  • QuerySelectorAll: Selects all the nodes
  • window.getComputedStyle: gets dynamic styles (External CSS files)
  • flat(): flattens arrays of arrays
  • split(/[^4],\s*/): If multiple backgrounds, split on comma, but do not split on base64,...
  • replace: remove url(...)
Denis TRUFFAUT
  • 1,017
  • 10
  • 11