// 03.May.2009

Create a Dynamically-resizing Background Image Using CSS

I came across an inter­esting little problem while working on a web pro­ject with the GF. She wanted to dis­play a back­ground image on her pages which would auto­mat­ic­ally fill the entire view­port, without tiling. She also wanted to be able to infin­itely resize the browser window and have the back­ground redraw accordingly.

“Oh sure,” says I, “we can do that. No problem.”

Only, it turned out to be a little trickier than I anticipated!

I quickly real­ised that there’s cur­rently no way to do this dir­ectly with the back­ground prop­er­ties.1 CSS3 provides a background-size para­meter that would’ve been per­fect. But with cross-browser CSS3 sup­port being about as imminent as the col­lapse of the sun, I had to find another solution.

After a couple of hours of Googling and with numerous false starts behind me, I even­tu­ally real­ised that what I needed to do was to build my design on three layers.

The first is simply the base layer. In this layer we define a width and height of 100% and we remove all pad­ding and margins:

html, body { margin: 0; padding: 0; width: 100%; height: 100%; }

The second layer con­tains the back­ground image. The image also has its width and height set to 100%. Additionally we set a z-index, pos­i­tion the image and “fix” its position:

#bg_image { position: fixed; top: 0; left: 0; z-index: 1; width: 100%; height: 100%; }

Our third and final layer is a con­tainer for the con­tent itself. This is an abso­lutely posi­tioned block with width and height set to 100% and a z-index that places it above the image layer:

#scrollable { position: absolute; width: 100%; height: 100%; top: 0; left: 0; z-index: 2; }

Thus the back­ground image is con­tained in a ded­ic­ated, fixed layer and the con­tent in a layer that sits on top of it. Both layers are com­pletely inde­pendent of each other.

As you can see, the CSS turned out to be rel­at­ively simple. Luckily enough, so is the HTML:

<body>
<div><img id="bg_image" src="/path/to/image.png" alt="" title="" /></div>
<div id="scrollable">
… content …
</div>
</body>

One div for the back­ground image layer and one for the con­tent. Easy!

It should be noted that the pro­file described above res­ults in a back­ground image that will be auto­mat­ic­ally res­ized in both the hori­zontal and ver­tical axes. More often than not this is going to result in a dis­torted image due to an incor­rect aspect ratio. This didn’t matter in the GF’s case because she wanted to use abstract images for her back­grounds and quite liked the res­ulting pixelisation.

If, how­ever, it’s important to retain the aspect ratio of your images, then only trivial changes are required to the CSS. The back­ground image I’ve used on the page, “25 Most Dangerous Programming Errors,” for example, res­izes only on the hori­zontal axis. The height of the image is gov­erned by the aspect ratio of the image rather than by the CSS. Thus its per­spective is main­tained and the image never looks dis­torted. Compare the source of that page with this and you’ll see only minor dif­fer­ences between them.

So, as you can see, this tech­nique offers a lot of flex­ib­ility for a very small expenditure in com­plexity. I’m glad I man­aged to figure it out (keeps the GF quiet anyway).

NOTE: To really see the magic in this, resize your browser window a few times and scroll around. This tech­nique has been tested in Safari, Firefox and Opera run­ning on OS X. Your mileage might vary. Those of you who are reading this in an RSS reader won’t be able to see any­thing dif­ferent — come on, get your arses on to the site!


  1. Please cor­rect me if I’m wrong!

Last Revision: May 12th, 2009 at 21:52
Short URL: http://wp.me/phEOu-pF (Tweet This!)


25 Comments for “Create a Dynamically-resizing Background Image Using CSS”

  1. Nice tip. One of these days I should really get around to learning CSS. And I mean *really* learn it. Not just hack around until some­thing appears to look mar­gin­ally as I intended but having no clue why

  2. For fun and frus­tra­tion in equal doses — try learning CSS!

  3. Great explan­a­tion. I’ve done this a few times in flash and I’ve been looking for a way to do it in CSS since part of me always feels like I’m “cheating” with flash…

    The one thing I’m trying to do dif­fer­ently is to add a fade-in effect with the entire page including back­ground using JQuery. Does anyone see any reason why the tech­nique described on this page could not be com­bined with the jquery fade in func­tion explained here?

    http://wdlog.com/tutorials/how-to-fade-all-the-pages-with-jquery/

    Let me know what you think! I’m pretty new to using javas­cript instead of flash for effects, so any insight would be awe­some. I’ll be your friend forever.

  4. I’m glad you like the tech­nique Bowser. I don’t see any reason at all why this tech­nique and the jQuery fade can’t be com­bined as you describe. In fact, I’m intrigued now. I’m going to try it out. I’ll doc­u­ment the res­ults here in a day or two (I’m kind of busy at the moment). Of course, if you get there first… please let us know here.

  5. You got it DarkBlue. I’m plan­ning to pick at it tomorrow so I’ll def­in­itely post when/if I get it sorted out.

  6. Thanks you saved the day with this one. It was so easy I failed the first time trying too hard. I spent hours on his in jquery and did not get it to work in all browsers. This has worked well enough!

  7. and how the heck did you get my user pick to show without me uploading it?!!! My god that was awesome!!

  8. @bradley: Always pleased to learn that what I write here has made a dif­fer­ence to someone, some­where. Your user pic­ture comes from the Gravatar ser­vice (http://gravatar.com/) where you pre­sum­ably have registered at some point. If you haven’t then please feel free to con­tinue to bow in awe at my most-amazing pro­gram­ming skills.

  9. wow .. that was amazing tech tip !
    will keep it in mind ! twit­ting out this art­icle @v_render @veeroo18

  10. No problem v-render. I’m glad it was useful to you. Thanks for the Tweets.

  11. thanks for this!
    could you please help me ?
    i had a code, but it doesn’t work
    i want the back­ground to auto­mat­ic­ally resize and fixed scroll

    code:

    body { background:#040507 url(http://i37.tinypic.com/29xxggp.jpg) top center no-repeat; height: 100%; left: 0px; pos­i­tion: abso­lute; top: 0px; width: 100%; z-index: 0; color:#bbb; font:12px/14px hel­vetica, arial,Sans-serif; }

    why doesn’t it work ?

  12. Because your code is incor­rect. You can’t make a back­ground render full­screen that way. Use the code I’ve posted here, it does exactly what you want and involves only a little extra code.

  13. […] Link to author’s blog […]

  14. Wow, this is cool and almost exactly what I’m looking for. I’m not good with CSS (yet, one day) but am using a nice JQuery image rota­tion func­tion. I want to give the illu­sion of rotating back­ground images. But I want to con­tain the height

    Here’s my ques­tion. How might I make the bg_image span the width of the browser window, but keep the image height fixed between a header and footer? It’s ok that the image distorts.

    Anyway, thanks for the great tutorial!

  15. @ChrisS: How do you mean my friend? Like this one?

  16. Hi, Jonathan. Thanks for responding!

    The client spe­cific­ally ref­er­enced a site using Flash (IANAFlashDeveloper) though that site changed a bit. But I think i can convey what was requested.

    Check out this site, and ima­gine the entire black area (where the video clip is placed) as an image, with the four rect­angles under the clip, layered over the bg image:

    http://www.thecorner.com/

  17. Just to add, the image would always be 100% of the width of the browser window, but the height (as you can see on thecorner.com’s black middle sec­tion) would always be fixed.

    I know, seems odd, but the cus­tomer is always yada yada yada.

  18. Okay ChrisS, I under­stand a bit better what you are trying to achieve now. You could cer­tainly do that with (X)HTML and CSS as my examples here illus­trate. However, as you’ve already indic­ated, your customer’s site is built on a Flash com­ponent and that’s a dif­ferent ball-game. I know it can be done in Flash, I’ve seen it on many sites, but I don’t know how. I have abso­lutely no idea about Flash devel­op­ment as it’s not some­thing I’ve ever worked with. Sorry.

  19. Oh sorry, I wasn’t being clear. That’s not my cus­tomer. That’s the site my cus­tomer wants to emu­late. I want to do this in CSS, not in Flash.

    Thecorner.com uses Flash, but I don’t. That’s why I’m here.

  20. @Chris S: Oh I see. My bad, I com­pletely mis­un­der­stood. I’ll email you dir­ectly and we’ll see if we can’t get it working between us.

  21. No problem, Jonathan. I’m easily mis­un­der­stood . I look for­ward to hearing from you. Thanks!

  22. Jonathan, thanks! This is a great simple solu­tion.
    I see that the image looses pro­por­tions, right?
    Take a look here: me.com
    What do you think is the trick used?

    Thanks,
    Laura

  23. I got it.
    2 images: one posi­tioned static at 50% the other in the bg set with the prop­erty to repeat-x and also set to be at 50%.
    This makes the visual trick.
    Thanks,
    Laura

  24. Exactly right Laura, in fact they could even use just a plain colour for the back­ground and set the main image above it.

    It’s easy to do this with the tech­nique I have described here, and it’s easy to main­tain the cor­rect aspect ratio (so the pro­por­tions aren’t lost). It all depends on just a couple of minor vari­ations in the CSS.

    Did you look at the other examples on this page, a couple have them have images that don’t loose their proportions?

    Kindest regards,
    Jonathan.

  25. Kool!!! Simply neat!

Contribute to the Discussion:

The comment handler is Gravatar enabled.