We've moved!

TechKnack.blogspot.com has officially moved to TechKnack.net. You should be redirected in 3-5 seconds. Thank you.

January 14, 2008

CSS trick - two background images

Add this post to Del.icio.us. Del.icio.us (0 saved)

Download Example

While using what I'm sure is my own idea of progressive enhancement on a web page, I came across an interesting situation: I wanted two background images, rather than one. My first background would be a general tiled image, to give the site's background a nice texture; the second a vertically-repeated image on the left-hand side, to be used in conjunction with a floating nav menu.

Now, while CSS3 is purported to support up to 8 background images -- no doubt to make rounded corners and other fancy borders easier for coders -- the problem is that, to the best of my knowledge, IE and FF don't yet support this feature. Besides that, IE6 and lower never will. And I'm not even sure this feature will be usable for what I want, anyway.

So, I had to have (ok, really, really wanted) the left-hand background, and, IMO, the page looked too bland without some texture on the general background. As I already had the structure of the page decided upon (and, as such, couldn't modify it for presentational purposes), I started looking at what I had to work with. There was obviously the body tag, but there was nothing much else to work with...besides the html tag itself.

I already had the vertical background applied to the body tag, so I started by removing the background color from body (so the html background could show through). I then applied the same background color and the new background image to the html tag:

html { background:#000 url("tiled.png"); } body { background:url("vertical.gif") repeat-y; background-position:75px top; }

And, whaddaya know, it worked! Unfortunately, it seems that declaring the html element's style in my CSS changes the basic behavior of the body element, making it more like a containing div. The result: there's a margin around the content, and the vertical background only goes to the end of the content. Yuck.

So, the first thing to do is fix the ugly margin. Easy enough: set body's margin to 0 , as well as body's padding for good measure. Next, fix body's background. Currently, the background stops at the end of the content area. Not a problem if the content causes the window to scroll, but not pretty if there's not enough content. I figure this should be easy enough to fix, just set body's height to 100%. This works well enough...in IE6. Strangely, FireFox 2 doesn't take so kindly to it. Changing the body's height to "auto" works alright, for both browsers, for overflowing content, but not for short content. A height of "auto" and a min-height of 100% works excellently in FireFox 2...but, again, IE6 doesn't know how to treat min-height. Good grief.

So, I enter the realm of CSS hacks. Using a min-height hack combined with advanced CSS selectors that aren't understood by IE6 and less, I combine the methods that worked for each browser into a series of rules that are "browser-filtered" - one browser uses one method, while another browser uses the next.

html { background:#000 url("tiled.png"); /* Height is 100%, so the body can be 100% */ height:100%; } body { background:url("vertical.gif") repeat-y; background-position:75px top; margin:0; padding:0; /* Height is 100%, so the tiled BG will tile all the way down the page, not just as far down as the page's content (when the content's height is less than the window's height) */ height:100%; } /* Hackety-hack-hack... FF2, with the above code, will only display the repeat-y image for as high as the window's viewport is; higher content (upon scrolling) will not have the bg. This "hack" makes the tiled background work properly in FF2. This type of "advanced selector" is not understood by IE6...dunno 'bout IE7. */ html>body { min-height:100%; height:auto; }

The common html code works fine on both browsers. It's only the body's height issue that needs resolved. The IE6 code is given in the body code; both browsers will see this and understand it. However, when they get to the html>body statement, IE6 says "wha??" and drops the rule, whereas FF2 says "ok..." and applies the appropriate styles to the body tag, overriding the earlier-mentioned height.


Rohman said...

I Andrew, i like your post. Very usefull for me. Thanks... greeting from indonesia..

EterniCode said...

I'm glad you found it useful :D

Harmen said...

Nice article :)
I, too, have experimented with using the BODY and HTML elements more effectively. If you're interested, check them out here and here.

Bryan Peters said...

I wrote about this in 2004 - check it out

Josh said...

Great post. Thanks for sharing your expertise.

I'm curious. Was there a reason for adding the padding-bottom to the body?

I'm on a mac so I haven't seen this on IE yet, but it appears to work fine without it.

EterniCode said...

Thanks, Josh, glad you liked it.

I'm afraid the padding-bottom:1em; is legacy code from my own implementation (which I obviously forgot to remove...oops). I used it to keep the page footer from being flush against the bottom of the page, which is where it was ending up when the content caused the window to scroll.

I'll go ahead and remove it, to avoid confusion ;) Thanks for bringing it to my attention!

Anonymous said...

thanks so much!!!!!

cakins said...

The technique seems intriguing, but I wish there were an example included. Am I just missing a link to an example somewhere in your article?

EterniCode said...

cakins: I hadn't considered putting together an example, the main reason being that I have no hosting other than blogspot :). I've now put a little something together using box.net, and put a download link to it in the article; you weren't missing anything ;)

Katelynian said...

I have been updating/making my blogger page stand out and as such, I made my own illustrated bg image for my blogger site. Unfortunately, I made the image the right size for my own browser/resolution but when shown on pretty much every other computer, the image is cut off in some place, or even too small on others.

I was wondering if this would work for what I would like to do, which would be dividing my bg image into two, right and left, and attaching them to their respective sides of the window. This way, in theory, no matter the size of the window the image would be fixed and the proper size.

I tried defining two backgrounds, the urls in the same place, separated by commas like I saw here but it... didn't work. :T

Here's my blog link, by the way.

Dan said...

Ooh - never thought to try this :). Thanks for the tip!

MH said...

Thanks a lot for your great work! You saved me a lot of time.

EterniCode said...

Katelynian, I can't believe I missed your comment! So sorry.

The comma-separated-values usage is a CSS3-only feature. As such, I believe the only major browsers to support it are Safari and Konqueror (if memory serves correctly). I think FireFox 3 and possibly Internet Explorer 8 will support the multi-background feature (as adept at passing Acid2 as they are), but I'm not sure.

Anyway, you could probably split the image, like you said, and use one image for each element. This would, in effect, be what has been termed the "Sliding Doors" effect, an effect that has been used in navigation tabs for a long time now. More on the technique at AListApart and Google. Just make sure your images have plenty of horizontal overlap for larger resolutions!


On a second look at your blog, it looks like you figured something out :) looks good, though there is a 40px gap when I maximize FireFox on my 1440x900 resolution screen ;)

Anonymous said...

awesome. thank you!

Jared Roussel said...

Extremely useful! Big kudos!