Wide Images In CSS Layouts

What Can Images Do To Your Layout?

So you've put together a fluid, tableless layout, structuring all of your columns using just CSS. You're feeling pretty good about things. Then you add your company's masthead image into one of these "fluid" boxes that grow and shrink as the user's window changes size.

It's then that you notice it.

The image is too wide. As soon as you go below a certain window width, the column the image is in becomes too narrow to fit the image. So your browser grows the containing box to hold that image. Unfortunately, that forces your other (floated) columns to be pushed down in order to make room for the image.

So now what?

Well, you could try to limit how narrow a page gets. As long as your images stay narrower than the minimum width its containing element will ever be, you'll never have to worry about this. But how do you do that? CSS gives us the min-width property. However IE doesn't recognize it. Not to fear, we can fake it, using javascript. Skidoo too is an example of such an implementation. There's some javascript in there that will limit the width of the page to 600 pixels. Now I can figure out what the minimum width an image's containing element will be and alter the image to fit as needed.

It's a good solution. It works. But what if you don't want to use javascript? Or what if you really want big images anyways? Well there might be another way to go about doing this.

Background Images

An alternate approach, and quite a handy trick, is to create an DIV block and use CSS to define its height the same as the image you want to place in your layout. The width of the DIV will automatically take up whatever horizontal space there is.

With your empty DIV define a background image that won't repeat, and is positioned in the middle of the block. As the window is sized and resized, the amount of width that DIV takes up will change, all the while displaying as much of your image as can fit inside the available space.

Here's a first example:

That image is 29,999 pixels wide. I don't care how big your monitor is, there's no way your going to fit that entire image onto the screen. But using the method described above, the image is cropped to a size that fits perfectly in the space provided.

The plus side to this is you can use any sized image you want and never worry about your users getting a screwed up interface. And this approach is actually very compatible. I've tested it back to IE 5 and Netscape 6.2 without any problems. (Netscape 4 isn't involved here.)

The downsides are there as well. First, you're creating HTML structure but not providing any "real" content. We're talking empty DIVs here. It's pure presentational logic and nothing else. A non-browser parsing your site isn't going to know there's an image there. The way around this is to include an IMG tag inside your (no longer) empty DIV and just set the display property to none.

Another downside is this is all a lot of work for just putting a stupid little image on your website. So I'm trying to bring the difficulty down to a minimum.

So lets look at the HTML

<div style="/*/*/background-image:url(very_wide.gif);" class="rsImage" ><img src="very_wide.gif" width="29999" height="50" alt="" ></div>

Despite how it looks, this is just an IMG tag wrapped by a DIV tag. The funny formatting is to keep the HTML readable while not allowing for any whitespace to appear between any of the tags in this block.

The IMG tag is there for non-CSS compliant browsers. They will ignore the inline CSS on the DIV and just display the image as expected. This is why the width, height and alt attributes are all defined, rather than just ignoring them.

About that inline style. Why am I using an inline style and what is up with that /*/*/ stuff? Well I'm using an inline style because if I have more than one of these on my page, and I'm keeping all my CSS in a separate stylesheet, I'll have to create unique selectors for each image I use this trick on. That's going to bloat your stylesheet and it means you have to edit both your HTML and your stylesheet when adding a new image to the page.

The only thing unique about this block from every other HTML block using this method is the actual image being used. By defining that as the background image via an inline style, I can keep all the other CSS needed to implement this in an external stylesheet, in a selector that can then be reused over and over for every image displayed in this way. In case you haven't already figured it out, the class name I'm using to store all this common CSS information is rsImage.

Now what about that /*/*/? That's simply a CSS comment hack to keep Netscape 4 from parsing the CSS. As of this writing, I cannot get Netscape 4 to play ball with this approach. But I'm using inline styles that will be processed by all CSS-knowledgable browsers, including Netscape 4. But I don't want Netscape 4 to use this CSS. Thus the comment hack.

As an aside here, I want to point out how you could potentially remove that comment hack and still be friendly to Netscape 4. Keep in mind that Netscape 4 is going to display the image in that IMG tag. So if you have a non-repeating background image aligned the same way the IMG element is (left, center, right) you're going to have one image overlap the other. Since they're the same image, they should overlay perfectly and the user won't be the wiser to the fact that you've stacked two images. It could work. But I'm not that bothered by the comment hack to try this approach. But you're free to give it a shot.

So that's the HTML. What about the CSS?

.rsImage { background-repeat: no-repeat; background-position: 50% 50%; } .rsImage img { width: 0; margin-left: -99999px; padding-left: 1px; }

The first thing you might notice is I don't perform a display: none on the image inside the DIV. Why is that? I'm after simplifying this as much as possible when it comes to adding a new image. One thing I want to eliminate is the need to specify the width property within the inline style. If I keep it to just defining the background color I can keep things forever simple when it comes to adding the DIV/CSS stuff.

By setting the width to 0 and then moving the image so far off to the left (via negative margins) that it won't appear on screen I am able to preserve the effect of the height of the image on its containing DIV. In other words, the div.rsImage block will have whatever height the image has without me having to specify it via CSS.

0 width should just hide the image completely. However Opera still displays 1px worth of the image. So that's why I had to apply the negative margins. The padding is there because IE will not recognize an element's existence if it has a 0 for one of its two dimensions. So you put all these different ways to hide the image but keep its height together and you've got a very compatible bit of CSS.

The .rsImage bit itself is very straightforward. It just sets the background image to appear in the center, middle of the DIV element and it says to not repeat that background image. Both of these values you can go ahead and change it, make copies and rename them, whatever. For mastheads, I like a centered image. For others, they want a left or right-aligned image, so go ahead and change the background position. Including the vertical-centering of the image really isn't necessary since the DIVs height and the image height will be the same, but I include it for completeness.

Columned Example

Here's a couple floated boxes sitting next to each other. You'll see this image approach works just fine.

Closing Thoughts

Try resizing this window a few times just to see this approach in action.

There's some bits to discuss on when to use something like this but I'm not going to cover that here. Instead, give it a try and get a feel for this yourself. You should be able to figure out when you need to use this and when you don't.

Good luck!