Dynamic Resize by Background Image
Not so long ago I came across a problem with dynamically setting the background images for my HTML elements. I wanted to let the user decide what background image to set for certain HTML elements through the cascading style sheet.
I did not want to bother the user with setting the dimensions of the background image, my code should handle this part automatically. To show why it’s not sufficient to just set the background image for a div element I created the following initial example:
< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Dynamic Background Image</title> <link type="text/css" rel="stylesheet" href="DynamicBackgroundImage.css" /> </head> <body> <div id="aDivElementWithDimensions"></div> <hr /> <div id="aDivElementWithoutDimensions"></div> </body> </html>
The cascading style sheet referred to by the name DynamicBackgroundImage.css in the HTML above, I put in the same folder and was pretty simple, two div elements with their background set, one element was specified with dimensions the other one wasn’t. Setting the dimensions of the second element I wanted to control dynamically:
#aDivElementWithDimensions
{
border: solid 1px #000000;
height: 285px;
width: 280px;
background-image: url(TestImage.jpg);
}
#aDivElementWithoutDimensions
{
border: solid 1px #000000;
background-image: url(TestImage.jpg);
}
For the test I found a suitable image of my daughter Mary, as we are under construction, she is wearing a helmet for safety:

As expected the first div element showed the background image whereas the other div element did not. The behavior was the same for both Internet Explorer 7 and Firefox 3.0.6 which I used for my experiments, figuring that there would be a pretty good chance it would work for other browsers as well if IE and FF3 worked.

My next naïve attempt at solving this problem didn’t work out very well, using a script on load I attempted to get the url for the background image so I could retrieve the dimensions and set the div element’s dimensions accordingly. I updated my HTML page with a JavaScript triggered on page load:
< !DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dynamic Background Image</title>
<link type="text/css" rel="stylesheet" href="DynamicBackgroundImage.css" />
<script type="text/javascript"><!--
function pageload()
{
// Get the element without dimensions
var theDivElementWithoutDimensions =
document.getElementById("aDivElementWithoutDimensions");
// Create a buffer image used to retrieve
// the dimensions of the image
var aBufferImage = document.createElement("img");
// Handle onload event to resize the div element
aBufferImage.onload = function()
{
// Thanks to JavaScript closure we can access
// the theDivElementWithoutDimensions variable
// from the onload method
with(theDivElementWithoutDimensions.style)
{
width = this.width+"px";
height = this.height+"px";
}
}
// Loading the image from the background image
// into the buffer image should trigger the onload
// event and allow us to set the dimensions for
// the div element
aBufferImage.src = theDivElementWithoutDimensions.style.backgroundImage;
}
--></script>
</head>
<body onload="pageload();">
<div id="aDivElementWithDimensions"></div>
<hr />
<div id="aDivElementWithoutDimensions"></div>
</body>
</html>
However my attempt was not in anyway successful, the second div element remained collapsed not showing the background image, so what was the problem?
Well it turns out that the background image when set from CSS is not available through the normal style property found on HTML elements, but there is a way around it using the computed style instead.
Of course the computed style is not implemented in the same way for IE and FF, that would have been a bit too easy, right
So to get the computed style without worrying about what browser is used, I added a little wrapper function:
function getStyle(elt)
{
var computedStyle;
if(typeof elt.currentStyle != 'undefined')
// IE
computedStyle = elt.currentStyle;
else
// Firefox
computedStyle = document.defaultView.getComputedStyle(elt, null);
return computedStyle;
}
From the computed style it is possible to get the URL for the background image; computedStyle.backgroundImage which will return url(“url-for-image”) in IE and url(url-for-image) in FF, adding a wrapper function for parsing the URL as well proved useful:
function cleanupUrl(aUrl)
{
var regExp = /^url\("?(.*?)"?\)$/ig;
var matches = regExp.exec(aUrl);
if(matches == null || typeof matches[1] == "undefined")
return null;
return matches[1];
}
With these functions added only a few adjustments were needed to the pageload-function in order to get it all up and running:
function pageload()
{
var theDivElementWithoutDimensions =
document.getElementById("aDivElementWithoutDimensions");
var computedStyle =
getStyle(theDivElementWithoutDimensions);
var dummyImage = document.createElement("img");
dummyImage.onload = function()
{
// Thanks to JavaScript closure we can access
// the theDivElementWithoutDimensions variable
// from the onload method
with(theDivElementWithoutDimensions.style)
{
width = this.width+"px";
height = this.height+"px";
}
};
dummyImage.src = cleanupUrl(computedStyle.backgroundImage);
}
Finally I got the wanted behavior and a greater understanding of the way this specific style sheet property can be access from JavaScript.

But instead of stopping here I wanted more, because over the last year or so jQuery has grown in popularity, and as Scott Hanselman last year announced on his blog; Microsoft will ship jQuery with ASP.NET MVC and Visual Studio.
I didn’t know so much about jQuery until last year when I started to use it and I was taking by storm! It is such an incredible framework, and so different from other AJAX frameworks I have worked with.
I wanted to try it out for my problem, so that I didn’t have to think about computed styles. I created a copy of my initial HTML page and included the jQuery files:
< !DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dynamic Background Image</title>
<link type="text/css" rel="stylesheet" href="DynamicBackgroundImage.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.pack.js"></script>
<script type="text/javascript">
function cleanupUrl(aUrl)
{
var regExp = /^url\("?(.*?)"?\)$/ig;
var matches = regExp.exec(aUrl);
if(matches == null || typeof matches[1] == "undefined")
return null;
return matches[1];
}
function ApplyBackgroundImageDimensions(elt)
{
// Get the baground image using jQuery,
// no need to worry about computed style
// because jQuery will handle that part
var backgroundImageUrl = cleanupUrl($(elt).css("background-image"));
// If no background image is set then return
if(backgroundImageUrl == null)
return;
// Create a dummy image to get the dimensions
// of the image
var dummyImage = document.createElement("img");
// When the image is loaded then set the dimensions
dummyImage.onload = function()
{
// Thanks to JavaScript closure we can access
// the elt variable from the onload method
$(elt).css("width", this.width+"px")
.css("height", this.height+"px");
};
// Get the URL for the background image
dummyImage.src = backgroundImageUrl;
}
function pageload()
{
// Get the element without dimensions
var theDivElementWithoutDimensions =
document.getElementById("aDivElementWithoutDimensions");
// Apply the dimensions from the background image
ApplyBackgroundImageDimensions(theDivElementWithoutDimensions);
}
$(document).ready(pageload);
</script>
</head>
<body>
<div id="aDivElementWithDimensions"></div>
<hr />
<div id="aDivElementWithoutDimensions"></div>
</body>
</html>
Neat, But way too clumsy! This ruins the simplicity which can be achieved with jQuery, so I had to figure out how to create a small extension for jQuery, making my code, simple and thus easier to read.
Making an extension to jQuery turned out to be really easy, after looking at a few examples I got the idea, and I created the file DynamicBackgroundImage.js to hold my extension in. I added one function called fitToBackgroundImage which can be called on any HTML element.
I should probably build in some more error handling, but that can wait.
/*
* jQuery Dynamic Background Image Plugin
* Requires jQuery v1.2.6 or later
*
* Copyright (c) Thomas Bindzus
* (http://bindzus.wordpress.com)
*
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
* Version: 1.0
*/
(function($)
{
$.fn.fitToBackgroundImage = function()
{
// Helper function to extract the URL from CSS
function cleanupUrl(aUrl)
{
var regExp = /^url\("?(.*?)"?\)$/ig;
var matches = regExp.exec(aUrl);
if(matches == null || typeof matches[1] == "undefined")
return null;
return matches[1];
}
// Returning the updated HTML elements in a
// way that allows for other jQuery methods
// to manipulate them further
return this.each
(function(index)
{
// Ensure we get a reference to the element
// which we can use closure on
var $this = $(this);
// Get the baground image using jQuery,
// no need to worry about computed style
// because jQuery will handle that part
var backgroundImageUrl = cleanupUrl($this.css("background-image"));
// If no background image is set then return
if(backgroundImageUrl == null)
return;
// Create a dummy image to get the dimensions
// of the image
var dummyImage = document.createElement("img");
// When the image is loaded then
// set the dimensions
dummyImage.onload = function()
{
// Thanks to JavaScript closure we can access
// the elt variable from the onload method
$this.css("width", this.width+"px")
.css("height", this.height+"px");
};
// Get the URL for the background image
dummyImage.src = backgroundImageUrl;
// Cleanup
dummyImage = null;
});
}
}) (jQuery);
With this addition finally true jQuery beauty arrived in my HTML page:
< !DOCTYPE html PUBLIC
"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Dynamic Background Image</title>
<link type="text/css"
rel="stylesheet"
href="DynamicBackgroundImage.css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.pack.js"></script>
<script type="text/javascript" src="DynamicBackgroundImage.js"></script>
<script type="text/javascript">
function pageload()
{
// Apply the dimensions from the background image
$("#aDivElementWithoutDimensions").fitToBackgroundImage();
}
$(document).ready(pageload);
</script>
</head>
<body>
<div id="aDivElementWithDimensions"></div>
<hr />
<div id="aDivElementWithoutDimensions"></div>
</body>
</html>
For this post I found useful information in a lot of places, main references resulting in my completion of this post are listed below:
https://developer.mozilla.org/en/CSS/background-image
https://developer.mozilla.org/en/DOM/window.getComputedStyle
http://blog.stchur.com/2006/06/21/css-computed-style
http://www.hanselman.com/blog/jQueryToShipWithASPNETMVCAndVisualStudio.aspx
http://docs.jquery.com
http://plugins.jquery.com/project/jqTooltip


Nice! But how would you go about dynamically resizing the background image accordingly to the element size it is in?
Jouni
8 May 09 at 12:23:44
Hi Jouni
I haven’t tried this, but I would get the dimensions of the element first and then set the dimensions for the background image accordingly, but if you want to get a resized image then I guess you would have to set the dimensions needed for the resized image back to the server-side as part of the URL and then resize the image dynamically on the server-side. This sounds like an interesting challenge, could you tell me more about what restrictions you want to have? Everything configurable through the CSS only?
Kind regards
- Thomas
Thomas Bindzus
11 May 09 at 02:09:47
Well one of the restrictions (of course) is that the image has to maintain its aspect ratio. And preferably everything should happen on the client side, and everything should also work with browsers that do not support CSS3
Resizing the image (and maintaining its aspect ratio) if it is loaded as an (or preloaded in JS) is not really a problem, but is there anyway to set the resized image as an element background without lets say.. saving the resized image on the servers hdd?
Jouni
11 May 09 at 13:13:22
This seems to be the same problem I am trying to think through. I want the user to be able to chose the colour of the background or to upload an image.
I have only just stepped into the problem so have some thinking to do first. But yes the uploaded image is going to need to be resized dynamically if the image meets the minimum requirements (don’t want the image tiled).
John
5 Aug 09 at 16:48:18
I didn’t find a feasible way to set the image as a background image, so I just made another element with an img inside it and made the two elements (the “background” and the actual content) “hover” over each other.
Theres some transparency in the “background” image, and getting alphablending to work in IE6.. well thats a different story.
Jouni
11 Nov 09 at 15:03:42
Hi,
I have to read the style.backgroundImage property of an element from JavaScript, and I’ve seen the “computed styles” approach but apparently there was (is) a bug in firefox preventing me from accessing that.
I’m just curious if you know of any other solutions for reading the backgroundImage?
Thanks,
D
David
17 Nov 09 at 09:02:17
I usually don’t post on Blogs but ya forced me to, great info.. excellent! … I’ll add a backlink and bookmark your site.
I’m Out!
online stock trading guru
11 Jan 10 at 06:30:30
Very excellent!
I have used this script for some projects and works fine. Best regards
Daniele
16 Jul 10 at 06:25:20