If you are looking for how to do FULL SCREEN BACKGROUND IMAGE, go here.
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? Offline
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 (Update Nov 2013: now offline), 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’!
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?
Cool stuff!
Here’s by the way a pure css implementation of the same thing.
oops, I forgot something: http://www.cssplay.co.uk/layouts/background.html
Thanks Anders! I have updated the article to include that solution as well, which looks to me like the best yet.
Beaverton, you never see that around the web. So where are you, Portland or Wisconsin?
@Jay: I’m in Portland now. Kind of lame my IP resolves to the beav =P
What’s the Weather? has a nice little JavaScript error:
haha is not defined
The line is:
var $winwidth = $(window).width();haha
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!
@NA: Thanks for noticing that. Looks like a random typo… got it fixed.
@Jake: No kiddin’ man. It’s a hot one today!
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.
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.
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).
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
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 :)
I actually love the script that grabs the weather… Am after something like this for WotUThink.com.
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.
depends where the center of focus is in your image.
i replaced:
top:0;
with
bottom:0;
thanks for the small tutorial.
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.
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.
Hi,
Great technique! I was wondering, would there be a way to applied something like to one block or colum?
Thank you
Oh Chris, I’ve been searching for you for so long. I am building a site in DW with drawn images in PS. I want to use them as background for each page and I need them to sit tight on the page just like the Weather, it just won’t work any other way. Trouble is I’m not a full bottle with code and don’t understand if you eliminated first three codes and went for the last? How do I get it in to DW, throught page properties ? I’ve tried every which way to resize in PS but it’s all guess work and either too large and starts to tile or too small with a white border. I am so desperate to move on and don’t understand when you speak in code. Would really appreciate help. Thanks Vicky.
Hi Chris, thanks for code. I have actually got this working albeit with a white border. I presume I now have to resize image to fit page. I have downloaded page dimensions plug in but am struggling to understand how to use. Will just have to keep going.
Thanks Vicky.
Hi!!
Is it possible to do this effect in a WordPress theme? I have tried, but it is not working for me…
Thanks!
Chris,
Your site is amazing and has helped me tremendously – not only to figure out how to do things, but also to see what kinds of things are possible within a browser window that I’d never thought of. I desperately need your help as it relates to a resizable background image – hopefully you see this comment.
The solution you’ve come up with here is great, but I’m looking for a little more proportional awareness – meaning, I’d like the background image to resize proportionally as you have it doing here, but then stop resizing if the user squishes the window to be much longer than it is wide. If a user does that with the solution you’ve come up with here on this post, you get white space underneath the image, which I don’t want. Here’s a flash site that does exactly what I want (though the background is video as opposed to a still image):
http://www.gudrungudrun.com/#/women/womenSpring/
See how the background resizes, but at a certain width/height ratio it stops resizing so that the image continues to fill the window? I believe this function is contained in a javascript file called, “swfforcesize.js”, but I’m not sharp enough with the old javascript to parse out what’s actually at play here.
Any idea how to replicate this for a non-flash background? Any help you could offer would be tremendously appreciated.
Thanks. Again, your site rocks.
I think the answer lies above in some kind of alternation to #2. Instead of just setting the width of the image to the width of the browser window, set it to the longest of either of the two sides (width of height). So no matter what, the width will be the longest and never create that white space.
Thanks, I’ll give it a whirl!
Tnx sharing this one, very useful for me.
Maybe I’ll try the javascript implementation.
Can we please get some clarification on this issue. None of these examples work entirely. Lots of good discussion of the issues though. I hope someone has a js solution to this.
I too would like to see some code example or the variation to #2 which prevents white space if the window is resized to width > height.
I’d like to get this to work on myspace. I know they don’t allow java scripts, or even a <.head>.
Can any of these codes be made to work within myspace?
This works for width, as noted, but still needs the proportion detection and adjustment for height as Chris Coyier noted. CSS is probably not able to detect these things, which is why you really need a javascript solution in order to handle all of this.
Has anybody made an implementation that solves the width OR height (proportion) thing?
I made another solution to a friend of a friend with resizable background image see this link
I’m searching for ages for a solution, where the background picture resizes and keeps the porportions. But I haven’t found a solution, where the picutre filles still the entire screen, when you resize it in height aswell..
If somebody has an idea..?
Hi Nathalie,
The solution you are looking fore is flash i think.
Cheers Thomas
Hi Thomas!
Well, Flash, JavaScript, CSS, HTML – I really don’t mind which one – I searched first mainly for Flash codes – but I haven’t found satisfying solutions. That’s why I started looking for JavaScript and CSS..
Any idea how to solve that with flash?
Cheers.
nath
Thanks, I’ll give it a whirl!
Nathalie, have you seen my post on nov 5th? Is that something you are looking fore in css, xhtml?
You need to use the right Doctype to get it right with IE. I know that IE 6 and sp 2 (xp) don’t work to good. I don’t care much about ie 6.
Love apple ;-)
i needed this for a site i am developing, and came up with this solution. it is pretty simple css. it allows the image to scale in width, but maintain proportions of the image.
anyway, i came here looking for idea how to do this, so thought i would drop this method off here for someone else.
Hi J. Im new to this, but your image scaling looks cool. I have been looking for a method how to doo this, after i saw the “go to china” site. Yours looks alot like it. How did you do this and in what program?
Hi J, this works really well. I presume this went in as a background image? How did you work out the correct size of your browser window? I also have links on my front page and need to make the links resize along with everything else. Any ideas. With thanks Victoria.
Thanks, I'll give it a whirl
Hi,
I think I am having the same trouble that Victoria had. I know some code, but need some help knowing what to change. Every time I try to change the picture to the one I want, the new picture just becomes a background and does not change size.
I think this is what everyone is looking for (minus the slideshow part of it).
http://www.adultswim.com/shows/index.html
Unfortunately, I can't tell how they're doing this.
@Tom
Same here. Anybody figures out how Adult Swim’s scaling words, let us know? Will post if I figure it out.
Er, how it works*, I mean.
It’s definitely the most elegant scaling solution I’ve seen. Dug through all of the js files I could find but they all pertained to the slideshow. No clues on the scaling yet. Unfortunately I’m still a javascript n00b.
Yes, it is very interesting. But page with long content doesn’t scroll, there is not scrollbar into your page.
You cam scroll the content here http://www.fiskebussen.se or the page
Personally, I think this here is a really nice solution.. no idea how it’s done.. too bad.. http://www.koeweidenpostma.com
Nathalie, that’s nice, but off-topic – that solution is entirely Flash – there’s no CSS about it.
Anyone get any further with this? I’ve been experimenting with setting the image to a minimum width, so as it scales to a certain point, then stays the same…… but er… that didn’t work.
I am trying to resize the background image without cropping any part of it. (no overflow:hidden) That I am sure we can do using height:100%.
I am having issue with applying the same to a particular section and the image is either stretched or compressed.
Any clue?
Oh boy :-( Just recently came up with the same topic: http://www.younic.de/scaling-body-background-images-with-pure-css But well, first come, first serve ;-)
I was wondering if you would take a look at http://www.treemendousplantworks.com/style.html
I’m working on a site for some friends whom have had a table based website. I’m not a CSS guru by any means and appreciated your tutorial on how to get the website background to stretch to fit using JavaScript. However, I’m have a hard to figuring out how to place my footer now so that it is at the bottom of the page. Can you firebug that page and let me know if you can suggest a fix for this problem.
Anything you can do is much appreciated.
Re:
Chris Coyer
I’d go with:
.bg {
bottom: 0;
left: 0;
position: fixed;
width: 100%;
z-index: 5000;
}
-Chris
https://css-tricks.com
Hey Chris,
That seemed like a good fix, but it didn’t work out. Some how now it is off the page all together. When I minimize the window and resize it can see that it is still on the page, but not in the footer area. Is there something in my footer css that is causing this discrepancy?
Thanks for the help!
Groundswell
Hi Chris-
I’m attempting to modify your code so that the image always fills the entire window. I’m not concerned about the window cropping the image, I just don’t want to see any white space.
The logic I’m going off of is this:
size the image to the window width
check to see if the image height > the window height
if it is, set the image width to the window width
if it is not, set the image height to the window height
Does this seem reasonable? The other part is, I’m not sure how to implement this with jsQuery. Think you could lend a hand?
I have managed to do this but what I didn’t do was place the image as a background image. I placed it in a layer as close to the size of the browser window as possible. Then placed the background colour the same as the background of the image colour. This gets rid of any white borders. Victoria.
I’m not totally clear on how the image proportions are maintained; I imagine it’s by just setting the image width in this line:
$("img.source-image").attr({
width: $winwidth
Is that the case?
Never mind. Got the footer figured out. It was in the footer tag after all. Thanks for your help Chris! Cheers!
~Groundswell
Chris,
I just wanted to thank you for the inspiration in this article, I saw this and began working on a jQuery fix, this article helped a lot in getting me rolling on that. I’m a big fan of the blog, thanks again.
Here’s my fix (browser compatible), it’s a jQuery plugin called Supersized –
http://buildinternet.com/2009/02/supersized-full-screen-backgroundslideshow-jquery-plugin/
This worked really well for me, I was pulling my hair out over this. Thanks Chris!
I would recommend making the
z-index
-1
so that the body can be on top of the image (like so):The Whats the weather link takes you to a spam site!. Please remove the link completely.
Wait a minute. Is it a background image or just an image? I know how to put a re-sizable image into a div, but I want a resizable background image. A background image is loaded through the css, and the advantage of using a background image is that it doesn’t hinder the page load time. Hence the need for a resizable background image. I think this tutorial is just teaching how to put an image into a div through html, and then styling the image through css. A true background-image needs to be loaded into the document like this:
Am I just not understanding this tutorial right?
Thank you for any feedback. I really would like some help with getting a re-sizable background image.
Used this as a css only way to use a retina image as a logo on Magento. Seems to work fine on retina and non-retina devices! Many Thanks!
phtml:
css:
.header .logo {
width: 289px;
height: 75px;
position: relative;
display: block;
}
.header-center a.logo img {width: 100%;
position: absolute;
top: 0;
left: 0;
}
Wouldn’t 2 simple css lines just work fine?