56

The problem is simple. How do I get a div's background image size (width and height) in jQuery. Is it even possible? I thought this would work:

jQuery('#myDiv').css('background-image').height();

The error message I get is that this is not a function.

Noah Passalacqua
  • 792
  • 2
  • 8
  • 24
Foad
  • 563
  • 1
  • 5
  • 4
  • Is the background fixed? Will it resize with the window, or do you just want to know the image that's bound as the background's information? – Brad Christie Feb 24 '11 at 14:54
  • 2
    You will need to load the background image into a `img` element and check the dimensions of that after it has been loaded – Pekka Feb 24 '11 at 14:55
  • No the background image is not fixed. It resizes with the window. The background image is centered and 100x100 px but the surrounding div is 500x500px. How can I get the width 100 and the height 100? – Foad Feb 24 '11 at 14:56

17 Answers17

91

One more version. No DOM manipulation needed, all characters in image file name supported.

UPDATE See an alternative version below.

var image_url = $('#something').css('background-image'),
    image;

// Remove url() or in case of Chrome url("")
image_url = image_url.match(/^url\("?(.+?)"?\)$/);

if (image_url[1]) {
    image_url = image_url[1];
    image = new Image();

    // just in case it is not already loaded
    $(image).load(function () {
        alert(image.width + 'x' + image.height);
    });

    image.src = image_url;
}

2018 solution

This answer is still receiving upvotes 5 years after. I thought I will share a more complete solution. This builds on top of original code and wraps it into a function. It uses jQuery Deferred Object, adds error handling and updates RegExp to match 3 possible cases: url(), url("") and url(''). It also works on jQuery 1 to 3.

var getBackgroundImageSize = function(el) {
    var imageUrl = $(el).css('background-image').match(/^url\(["']?(.+?)["']?\)$/);
    var dfd = new $.Deferred();

    if (imageUrl) {
        var image = new Image();
        image.onload = dfd.resolve;
        image.onerror = dfd.reject;
        image.src = imageUrl[1];
    } else {
        dfd.reject();
    }

    return dfd.then(function() {
        return { width: this.width, height: this.height };
    });
};

//
// Usage
//
getBackgroundImageSize(jQuery('#mydiv'))
    .then(function(size) {
        console.log('Image size is', size.width, size.height);
    })
    .fail(function() {
        console.log('Could not get size because could not load image');
    });
Vilius Paulauskas
  • 3,121
  • 3
  • 24
  • 24
  • 1
    `slice` is standard, `substr` isn't; `.slice(4, -1)` to remove `url( ... )` – Dan Lugg Mar 01 '13 at 19:18
  • 2
    No prob :) I believe yours should be the accepted answer. While the others will work the majority of the time, even the most trivial ones can be fragile. I don't see how this could break, nor does it add unneeded complexity. – Dan Lugg Mar 02 '13 at 15:54
  • 4
    Potential pitfalls: see "Caveats of the load event when used with images" http://api.jquery.com/load-event/ – Andy Dec 20 '13 at 16:33
  • I could only get this to work using the [imagesLoaded jQuery Plugin](https://github.com/desandro/imagesloaded). – Reed Martin Apr 08 '17 at 13:26
  • 2
    This does not work with an image that scales down (ie, when using `background-size: contain;`) - it gives the 'native' image properties, but not the ones its being displayed at. – kneidels Sep 07 '17 at 11:44
33

You'll have to do something like this:

var url = $('#myDiv').css('background-image').replace('url(', '').replace(')', '').replace("'", '').replace('"', '');
var bgImg = $('<img />');
bgImg.hide();
bgImg.bind('load', function()
{
    var height = $(this).height();
    alert(height);
});
$('#myDiv').append(bgImg);
bgImg.attr('src', url);

Due to the simplicity of the code, you cannot use parenthesis or quotation marks in the URLs of your background images. However, the code could be extended for greater support. I just wanted to convey the general idea.

John Kurlak
  • 6,594
  • 7
  • 43
  • 59
  • 3
    it is better to replace all the '"', so you can use: var url = $('#myDiv').css('background-image').replace('url(', '').replace(')', '').replace(/'/g, '').replace(/"/g, ''); – Jimmy Huang May 26 '11 at 04:08
  • 3
    Hopefully anyone reading these answers reads this comment. This answer is NOT a good practice. Appending the background image to the DOM is a mistake, as is removing it from the #myDiv css. It is easier, faster, and far safer to grab the dimensions in similar manner retrieved here (done better in answers below), and to then use them to change the `background-size` attribute to your liking. – runspired Apr 04 '13 at 18:14
29

Late answer, but you could also do this:

var img = new Image;
img.src = $('#myDiv').css('background-image').replace(/url\(|\)$/ig, "");
var bgImgWidth = img.width;
var bgImgHeight = img.height;

Then you don't have to manipulate the dom objects;

Jon
  • 504
  • 5
  • 6
4

Another short way :

function bgSize($el, cb){
    $('<img />')
        .load(function(){ cb(this.width, this.height); })
        .attr('src', $el.css('background-image').match(/^url\("?(.+?)"?\)$/)[1]);
}

usage

bgSize($('#element-with-background'), function(width, height){
    console.log('width : ' + width + ' height : ' + height);
});

https://jsfiddle.net/x4u2ndha/58/

Freez
  • 7,208
  • 2
  • 19
  • 29
3

I merged the answer from John together with the Plugin Style from Stryder. This plugin waits for the image to load:

$.fn.getBgImage = function(callback) {
    var height = 0;
    var path = $(this).css('background-image').replace('url', '').replace('(', '').replace(')', '').replace('"', '').replace('"', '');
    var tempImg = $('<img />');
    tempImg.hide(); //hide image
    tempImg.bind('load', callback);
    $('body').append(tempImg); // add to DOM before </body>
    tempImg.attr('src', path);
    $('#tempImg').remove(); //remove from DOM
};


// usage
$("#background").getBgImage(function() {
    console.log($(this).height());
});

feel free to extend this code: https://gist.github.com/1276118

schmidsi
  • 184
  • 1
  • 5
2

Maybe few possibilities, I've tried to simplify as much and finaly this works for me

var img = new Image ;
img.src = $('#dom').css('background-image').replace("url(", "").replace(")", "").replace("\"", "").replace("\"", "");
$(img).load(function() {
    var bgImgWidth = img.width;
    var bgImgHeight = img.height;
    console.log("w::"+bgImgWidth+",h::"+bgImgHeight) ;
}) ;
Christophe
  • 17
  • 3
2

Its been a while but I needed this solution as well, based on some suggested solutions here is my complete solution.

$.fn.getBgHeight = function () {
        var height = 0;
        var path = $(this).css('background-image').replace('url', '').replace('(', '').replace(')', '').replace('"', '').replace('"', '');
        var tempImg = '<img id="tempImg" src="' + path + '"/>';
        $('body').append(tempImg); // add to DOM before </body>
        $('#tempImg').hide(); //hide image
        height = $('#tempImg').height(); //get height
        $('#tempImg').remove(); //remove from DOM
        return height;
    };
Stryder
  • 1,421
  • 1
  • 10
  • 6
2

I made the same thing for the width :)

$.fn.getBgWidth = function () {
    var width = 0;
    var path = $(this).css('background-image').replace('url', '').replace('(', '').replace(')', '').replace('"', '').replace('"', '');
    var tempImg = '<img id="tempImg" src="' + path + '"/>';
    $('body').append(tempImg); // add to DOM before </body>
    $('#tempImg').hide(); //hide image
    width = $('#tempImg').width(); //get width
    $('#tempImg').remove(); //remove from DOM
    return width;
};
Jankeesvw
  • 711
  • 8
  • 18
1

The following is my adaptation:

$.fn.getBgDim = function (callback) {
    var width  = 0,
        height = 0,
        path   = $(this).css("background-image").replace("url(", "").replace(")", "").replace("\"", "").replace("\"", ""),
        tmp    = $("<img />");
    tmp.hide();
    tmp.bind("load", function() {
        width = $(this).width(); 
        height = $(this).height();
        callback({"width": width, "height": height});
        $(this).remove();
    });
    $("body").append(tmp);
    tmp.attr('src', path);
};

Usage:

$("#image").getBgDim(function(dim) {
    console.log("Height: " + dim.height + " Width: " + dim.width);
});
Bas
  • 31
  • 2
1

Here is my rendition.

$.fn.getBgImage = function (callback) {
    var path = $(this).css('background-image').match(/^url\("?(.+?)"?\)$/)[1];
    var tempImg = $('<img />').hide().bind('load', function () {
        callback($(this).width(), $(this).height());
        $(this).remove();
    }).appendTo('body').attr('src', path);
};

Usage:

imgDiv.getBgImage(function (imgW, imgH) {
    //use the imgW and imgH here!   
});
box86rowh
  • 3,415
  • 2
  • 26
  • 37
1

css('background-image') will return "url(.....)", you can't test the height of the image with that, since it's not a DOM object.

Capsule
  • 6,118
  • 1
  • 20
  • 27
1

the same as above, but using regexp instead of replace()

$.fn.extend({
    /**
     * gets background image
     * @param callback function (inside - this = HTMLElement image)
     */
    get_bg_image: function(callback) {
        if (typeof callback != 'function') return;
        var regexp = /url\((.+)\)/i,
            regexp2 = /["']/gi,
            res = regexp.exec($(this).css('background-image')),
            img_src = res[1].replace(regexp2, ''),
            $tempImg = $('<img />');
        $tempImg.hide();
        $tempImg.bind('load', function(e) {
            callback.call(this, e);
            $tempImg.remove();
        });
        $('body').append($tempImg);
        $tempImg.attr('src', img_src);
    }
});

// usage
$('div').get_bg_image(function() {
    var bg_img_width = $(this).width();
});
xramonz
  • 11
  • 3
0

Combined version of the above solutions

var width,
    height;

$(image).load(function () {
    width  = image.width;
    height = image.height;
});

image.src = $('#id').css('background-image').replace(/url\(|\)$/ig, "");
holger
  • 9
  • 1
0

In the case your css had double quotes or browser manipulation do the following.

var url = $('#myDiv').css('background-image').replace('url(','').replace(')','').replace('"','').replace('"','');
var bgImg = $('<img />');
bgImg.hide();
bgImg.bind('load', function()
{
    var height = $(this).height();
    alert(height);
});
$('#myDiv').append(bgImg);
bgImg.attr('src', url);
Designaroni
  • 112
  • 1
  • 10
0
// The above all solutions may work in all browsers except IE11 so below is the modified solution for IE11 browser
//The height calculated for IE11 wasn't correct as per above code

$.fn.getBgImage = function(callback) {
  if (typeof callback != 'function') return;
  var regexp = /url\((.+)\)/i,
      regexp2 = /["']/gi,
      res = regexp.exec($(this).css('background-image')),
      img_src = res[1].replace(regexp2, ''),
      $tempImg = $('<img />');
  $tempImg.hide();
  $tempImg.bind('load', function(e) {
      callback.call(this, e);
      $tempImg.remove();
  });
  $('body').css({ 'width': 100 + '%' });
  $tempImg.css({ 'width': 100 + '%' });
  $('body').append($tempImg);
  $tempImg.attr('src', img_src);
}
0

In my particular case, I needed something which would work with background-image: linear-gradient(rgba(0, 0, 0, 0.4),rgba(0, 0, 0, 0.4)), url(...). I needed also a code that would be able to check several image from a specific class without copying the code for each image.

Maybe it could be useful for someone ! (I'm absolutely not an Jquery expert, since I started to code a month ago for my personal website.. So feel free to correct if needed !)

This work latest jQuery 3 and IE11 too. for backward JQuery compatibility, I think you can only replace .on("load", function() by .load(function().

//will check all div with this class or id
var $image = $('#myDiv');
//will extract url only by splitting property on comas (takes care of comas on rgba(x, x, x, x))
var imageUrl = $image.css('background-image').split(",")[8].replace('url(','').replace(')','').replace('"','').replace('"','');
var img = new Image ;
img.src = imageUrl;

$(img).on("load", function() {
  var image_width = img.width;
  var image_height = img.height;
  console.log(image_width + " x " + image_height) ;
}) ;
Lyddark
  • 61
  • 2
0

This is the most popular question regarding this topic, so I have to say that I don't understand why people try to overcomplicate things. Also I have to admit that I don't know how on earth one can call load() JQuery function with just one parameter which is callback, since the method takes 3 parameters. As far as I am aware this would cause 'IndexOf()' is not defined exception. I don't know if I am missing sth or the API has changed so much over the years. Anyway here is a working solution as of 2020:

jQuery.fn.extend({
    backgroundImageSizeAsync: async function() {
        const imageUrl = this.css("background-image").match(/^url\("?(.+?)"?\)$/)[1];
        const image = new Image();

        await $.Deferred(function (task) {
            image.onload = () => task.resolve(image);
            image.onerror = () => task.reject();
            image.src = imageUrl;
        }).promise();

        return {
            width: image.width,
            height: image.height
        }
    },
});

call:

const size = await $(selector).backgroundImageSizeAsync();
rvnlord
  • 3,487
  • 3
  • 23
  • 32