Fluid Images (and How to Make Them Look Nice in Internet Explorer 6 & 7)

Last week, I joined PatientsLikeMe full-time. I’ve known them for quite a while, though. In fact, over the past couple of years they have been my biggest (well, one of very few) freelance clients. My most recent work for them was to build the markup and style for new site for partners from a series of mockups. (Portfolio page is here.)

The Problem

Here’s what the homepage looks like. I can dig it.

PatientsLikeMe Partners home page

The header, sidebar, and footer are pretty straight forward. That large graphics-and-text element in the main column is a bit different. So, how would I go about marking this up? First of all, the photos and screenshots are presentational, so we’d handle that with a background image. For the text (which is not presentational, so we want it in the markup), I tend to size using keywords and percentages. But in a case like this, I’d use some pretty pixel-specific font sizing, padding, and line breaks to get the markup to render like the mockup. Of course, I’d have to use some sort of image replacement on the “Patients + Data” title since that’s a non-standard font.

But Wait!

Here’s the thing. The page is actually somewhat fluid. It has a min-width of 1000 pixels and a max-width of 1200 pixels. So, even if I wanted to use that approach, I have no way of knowing exactly where the text should go because the image behind it doesn’t have a static size.

So… now what?

Well, we’re gonna rock it like it’s 1999 and just use one big honkin’ image for the main column. It’s not the most elegant solution, but it will work the best. To ensure the text-based content is still available of the user turns images off, we’ll put the text in the markup. Like so:

<div id="image">
  <h2>Patients Data = Insight</h2>
  <p>Patients are no longer just health care consumers. They are healthcare customers. <strong>PatientsLikeMe</strong> provides deep insight into your target patients&rsquo; attitudes, beliefs, behaviors, and outcomes.</p>
  <p><a title="Learn more about our Products &amp; Services." href="products/">Learn More&nbsp;&raquo;</a></p>
  <a title="Learn more about our Products &amp; Services." href="products/"><img src="images/home1.jpg" alt="Home page artwork" width="864" height="735" /></a>
</div>

You see I have the text and the image present. I’ll use CSS to offset the text while keeping the image visible. That CSS looks like:

div#image h2, div#image p {
  position: absolute;
  left: -1000px;
  width: 100px;
}

Why use this instead of display: none;? Setting display: none; on an element will completely remove it, even for users with assistive devices such as screen readers. The offset technique will just push the content out of the viewport. It’s still actually there, just not visible. Users with CSS and images enabled will see the image and no text. Users with screen readers will simply read the text (and alt text of the image). Users with CSS AND images turned off will see just the text. The rare folks that have CSS turned off but images turned on will get both the image and the photo. I believe that’s a small enough population to make this an acceptable approach.

But Wait Again!

We’d actually like this image to fill the main column, whether the screen is at 1000 pixels wide, 1200 pixels wide, or somewhere in between. How do we do that?

div#image img { max-width: 100%; height: auto; }

In the markup, hard-code the image’s width to fill the maximum width of the area. In the case above, it was 864 pixels. Then, the max-width: 100%; ensures that if the width of the div shrinks, the image will shrink along with it. The height: auto; simply will adjust the height of the image to correspond with the new width.

Awesome, right?

Oh, the IE Horror!

The good news is that all the markup and CSS above works fine with Internet Explorer. Yes, even IE6. However, it’s the godawful way that IE resizes images that causes the problem.

Luckily, through a bit of hunting I found that by simply adding some weird proprietary Microsoft thingie to your CSS, you can fix it. I just added this line to my IE stylesheet:

div#image img { -ms-interpolation-mode: bicubic; }

You can see the before and after below. Pretty remarkable difference. It becomes really noticable when there is text in the image.

ms-interpolation: bicubic; - Demo

One caveat: I tried to use this technique on a PNG file. It didn’t work. However, I re-saved the image as a high quality JPG and it worked. So I suppose Microsoft assumed you would only want to do this for photos or something?

One more caveat: If you have many images on the page with -ms-interpolation-mode: bicubic added to them and do any window resizing, things can get slow really quickly. Ethan Marcotte wrote a more complicated but higher performance method for handling this. If you’re talking one or two images on a page though, you’re fine with this approach.

And there you have it. Your image will stretch to your desired max- and min-width, and even look nice in Internet Explorer 6 and 7 (IE8 actually resizes images like a real web browser).

One Comment

  1. On October 21st, 2009 at 8:31 am Ethan said:

    Awesome write-up! I loved the process breakdown, and really appreciated the link. We actually discussed -ms-interpolation-mode a bit in my Fluid Images entry: it’s IE7+ only, sadly, and won’t work on PNGs (as you’ve seen).