How To: Resizeable Background Image
My friend Richard recently came to me with a simple CSS question:
Is there a way to make a background image resizeable? As in, fill the background of a web page edge-to-edge with an image, no matter the size of the browser window. Also, have it resize larger or smaller as the browser window changes. Also, make sure it retains its ratio (doesn’t stretch weird). Also, doesn’t cause scrollbars, just cuts off vertically if it needs to. Also, comes in on the page as an inline <img> tag.
Wow, that’s a tall order. My first thought was… uhm, No. But of course this is just the kind of challenge I enjoy, so I set about to thinkin’. Ultimately, I found a pretty good solution and we turned it into a pretty neat little project. First, check out the finished project, then I’ll show you how it was done:
Finished Project: What’s The Weather?

Go ahead and resize your browser window around and notice how the image will resize to fit. It doesn’t do it “on the fly”, but it does work. It also meets all the other requirements: no scrollbars, and retains pixel ratio.
First Attempt
Well my first thought was that this really needs to be a CSS background-image. This will fill the screen edge-to-edge if the image is big enough. It also can be centered, so I figured this would be good enough. Large browser windows will reveal more of the picture and smaller ones less of the picture. If applied to the body tag, this will fill the screen nicely with no scroll bars. Pretty good solution I thought, even if it isn’t technically resizeable, since you can’t set the size of a CSS background-image. Here is how I went about this first approach.
<head>
....
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("img.source-image").hide();
var $source = $("img.source-image").attr("src");
$('#page-body').css({
'backgroundImage': 'url(' + $source +')',
'backgroundRepeat': 'no-repeat',
'backgroundPosition': 'top center'
});
});
</script>
</head>
<body id="page-body">
<img class="source-image" src="images/image.jpg" alt="" />
</body>
You guessed it, jQuery. The above code will hide the image on the page, but snag it’s “src” attribute and apply it as a background to the body element (via its unique ID “page-body”). Check out an example of this in action.
Second Attempt (better)
While the first attempt did a decent job, it failed at the most fundamental level: it wasn’t “resizeable”. So time for another take. In order to control the size of an image displayed on the screen without literally altering the file itself is to display it inline with the <img> tag. With the img tag, we can set “width” and “height” attributes to control the image’s size. If we can get our hands on the exact pixel width of the browser window, we can use that number in the width attribute of the image and control its size while retaining the ratio.
We can, again, use jQuery and the dimensions plugin to get our browser window’s width. Then we’ll use that number to set the width attribute on the image, which we’ll give a unique class name “source-image”. We will need to do this as soon as the DOM is ready so it happens before the image even starts loading. We can also do this (FTW) any time the window is resized. Here is how it goes down:
<script type="text/javascript" src="/js/jquery.js"></script>
<script type="text/javascript" src="/js/jquery.dimensions.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var $winwidth = $(window).width();
$("img.source-image").attr({
width: $winwidth
});
$(window).bind("resize", function(){
var $winwidth = $(window).width();
$("img.source-image").attr({
width: $winwidth
});
});
});
</script>
In order to get this inline image to behave more like a background image, we can use that unique class we applied to apply some absolute positioning.
img.source-image {
position: absolute;
top: 0;
left: 0;
}
Because of this absolute positioning, anything that you want to put over it will also need positioning and a higher z-index value. If your source image is particularly tall, or your browser window is particularly wide, the image could easily become taller than your browser window and force a vertical scrollbar. In order to prevent this, simply set the overflow value on your body to hidden:
body {
overflow: hidden;
}
Third Attempt (best)
Forget this javascript business! Thanks to Anders comment pointing out Stu Nicholls version, here is an even better way to handle this without the need for any javascript at all!
Since we already have a unique class on the image, the image is absolutely positioned, and the scrollbars thing is already taken care of, let’s just set the width using a percentage directly in the CSS:
#img.source-image {
width: 100%;
position: absolute;
top: 0;
left: 0;
}
See a demo of this in action. This is the best solution yet, because the resizing happens on-the-fly for a nice fluid feel, and doesn’t rely on any javascript whatsoever.
More about WhatsTheWeather.net
I just did the simple design for What’s The Weather, but Richard did all cool coding to make it work. From what I understand, it is a chain of 3 different APIs. First it gets your IP address and uses an API to turn that into a city and state. Then it uses some weather API to get the current weather. Then it uses the Flickr API to get a random image with tags that match the weather. If if it can’t get your zip, it will ask you for it, like on the iPhone (which it also auto-detects and handles a bit differently). All done up with Ruby on Rails. Pretty fancy dancin’!














1
good stuff!
“What’s The Weather” has the gnarly blue img border rendering in IE6, I think it’s just missing the border=”0″ tag?
Comment by bolo — May 15, 2008 @ 5:55 am
2
Cool stuff!
Here’s by the way a pure css implementation of the same thing.
Comment by Anders — May 15, 2008 @ 6:47 am
3
oops, I forgot something: http://www.cssplay.co.uk/layouts/background.html
Comment by Anders — May 15, 2008 @ 6:47 am
4
Thanks Anders! I have updated the article to include that solution as well, which looks to me like the best yet.
Comment by Chris Coyier — May 15, 2008 @ 7:02 am
5
Beaverton, you never see that around the web. So where are you, Portland or Wisconsin?
Comment by Jay — May 15, 2008 @ 10:03 am
6
@Jay: I’m in Portland now. Kind of lame my IP resolves to the beav =P
Comment by Chris Coyier — May 15, 2008 @ 10:11 am
7
What’s the Weather? has a nice little JavaScript error:
haha is not defined
The line is:
var $winwidth = $(window).width();haha
Comment by NA — May 17, 2008 @ 9:54 am
8
Wow, I really like that site Chris, nice job. I just across the river, I can’t believe it’s fricken 95 out! Crazy weather!
PS…. Love the css-tricks footer!
Comment by Jake-DesignerFied — May 17, 2008 @ 5:28 pm
9
@NA: Thanks for noticing that. Looks like a random typo… got it fixed.
@Jake: No kiddin’ man. It’s a hot one today!
Comment by Chris Coyier — May 17, 2008 @ 6:45 pm
10
Pretty cool! However you should include a way to check if the window is taller than the image to resize again and get rid of the white space that appears under some of them. I guess that means setting a height attribute in pixels and then applying a bit of math to work out the width and keep a constant ratio.
The effect is quite neat, regardless.
Comment by Roberto — May 19, 2008 @ 7:24 pm
11
Brilliant.
Simple.
Elegant. In the true sense of the word. I had been looking for something like this a while ago, but fell back on using a larger image, and using overflow: hidden to keep the structure of the page (if not the whole image).
Thank you.
Comment by Karl Hardisty — May 19, 2008 @ 9:27 pm
12
Probably not important to your weather pages, but setting overflow: hidden; on the body can cause problems in Firefox when you want to print a page that’s longer than one sheet of paper. As the content overflows the sheet only the first sheet will be printed. The second sheet will probably contain one more line but the rest of it will be empty.
It’s something to keep in mind when using overflow: hidden; on large block elements (not just the body).
Comment by Sander Aarts — May 20, 2008 @ 4:36 pm
13
Sander,
thank you for the heads up. We are aware of this and have been searching for a fix (with no luck so far).
Regards,
Karl
Comment by Karl Hardisty — May 20, 2008 @ 5:05 pm
14
You might want to make sure the ratio on the image is at least 4:3 to get rid of the unnecessary whitespace below the image… and make sure that if the bottom part of the image gets cropped off, nothing important is missing
Comment by Matijs — May 21, 2008 @ 1:08 am
15
I actually love the script that grabs the weather… Am after something like this for WotUThink.com.
Comment by Jermayn Parker — May 21, 2008 @ 8:01 pm
16
I’ve got something like that on my temporary splash page while I sort out my work, it’s just a large css-centred image which gives pretty much the same effect.
Comment by Alex Moyler — May 22, 2008 @ 7:36 am
17
depends where the center of focus is in your image.
i replaced:
top:0;
with
bottom:0;
thanks for the small tutorial.
Comment by tudor — June 18, 2008 @ 3:39 am
18
So, what about IE6? Sucks that people still use this absolutely horrible browser, but I have a client who needs a dynamic background image that resizes and also has visitors who still use IE6. IE < 6 luckily enough, represents less than a percent of the visitors so I don’t have to worry about THAT browser.
Comment by Eric — July 6, 2008 @ 5:31 pm
19
Fantastic.
One thing about whatstheweather though… could you have it detect which countries use Celcius/metric (like here in Australia), rather than imperial (it’s default) and change the temperature info accordingly. It got my city right (Perth, WA), but the weather isn’t “slightly cloudy” atm (it’s thunderstorms and hail), and fahrenheit means nothing to me. Once you detect if the city is in a metric country, then you could do a small conversion of whatever the fahrenheit is, to metric.
Anyway, love the proof of concept. I think it’ll be a while though before we all have decent enough internet speeds to be able to use it.
Comment by storm — July 17, 2008 @ 8:20 pm