HTML & CSS - - By Alex Walker

Stretchy Images with HTML and CSS

The following is a little piece published in the last Design View.

At the time of publishing, I noted that IE7 allowed you use CSS to set an image width to a percentage (for instance, 30%), but that it failed to re-calculate that percentage if you resized the browser and a full refresh was required to force the graphic to resize.

Resident CSS guru and co-writer of our new CSS reference, Paul O’Brien has pointed out a nice solution to this bug that I’ll detail below.

**************************

Sometimes, the Web’s greatest strength can also be its biggest Achilles’ heel.

As clever as web content can be at reformatting itself for different devices and screen sizes, there’s one layout issue I always battle with — the fact that liquid site layouts stretch and images don’t.

While a layout can stretch and contract, and text can flow and wrap, images are assigned a pixel size at birth, and that’s precisely how they’re displayed thereafter, regardless of their surroundings.

In most typical article or blog post layouts, this doesn’t present a huge issue. On a really large screen, the images might seem a little undersized, but as long as the text flows around the image correctly, it usually just looks little text heavy, rather than plain wrong.

I see this issue mostly in graphical site headers and image heavy promos (like the one below). Typically the more balanced and composed they look at smaller browser widths, the more strung-out and weedy they look on wide screens.

A good example of a layout that works well at a smaller format, but that begins to tear itself in half on a wide screen.So, what are your options for resizing these layouts?

1) Adobe Flash: Vectors graphics will always be the ideal tool for resizing and Flash has always been a vector tool at heart, so if your original imagery is mainly vectors, there are some compelling reasons for embedding the whole thing in an SWF.

2) Canvas: The canvas element is part of the new HTML5 spec, and is currently surprisingly well supported by most of the leading browsers. The canvas tag (<canvas>) itself is nothing more than an empty drawing space waiting for us to fill, but you’ll need some JavaScript voodoo to make good use of it.

For now we’ll leave canvas alone, but it looks to be presenting some really interesting options, so we’ll return to it in the Design View in the near future.

3) Smart Image Resizing/Seam Carving: Seam carving is probably the buzz word of 2007, and if you’ve been following the SitePoint blogs and forums over recent months you’ll likely already be aware of the idea. This is exactly the kind of situation in which seam carving would shine.

Unfortunately, although the concept is brilliant, a way to deploy it within a page still looks to be at least a few months away at this stage, and will likely rely on Flash.

However, while we wait for better technology, I’ve come up with an alternative method for resizing imagery in certain situations. It certainly isn’t applicable in most situations, but if you keep it in mind when you’re planning your imagery, it might be a nice trick to keep up your sleeve.

Stretchy images in actionFirstly, let’s have a look at the stretchy image in action. To the right is an animation showing the stretch, and I’ve set up a working example here. Almost identical code is running live on the SitePoint home page (in rotation), but I’ve separated it out to a standalone page to make things simpler.

As you can see, as you stretch your browser wider, the three “feature boxes” move away from the book image, while the ‘connecting arms’ stay connected. While the effect eventually fails at super-wide and very low resolutions, it certainly deals with the available space much more elegantly than a standard image ever could — all without requiring any special technology or complex scripts.

The Method

Of course, browsers can and always have been able to resize images on the fly. It’s just that they’ve always done such a rotten job at it, so we designers tend to ignore that ability.

The key to this trick is limiting the stretchiness to the parts of the graphic that matter the least — in this case, the connecting arms.

Stacking order diagram

Our image is composed of three smaller, overlapping graphics, each of which is set to position:absolute, which just simplifies the whole process of overlapping them. The wrapping DIV that contains them is set to position:relative to keep them inside their box.

Stretchy images in actionGraphic 1: The Book

The book itself is a transparent PNG8 and set to left:55% — this will make sure it’s always positioned a little over half way across the container DIV, regardless of its width. I’ve also set it to top:-1em so that the top edge of the book pokes out of the box. We don’t want this image to distort at all, so we give it it’s natural dimensions — 139x197px.

Lastly, I ensured that the book image would always be in front of everything else by setting its z-index to 99. This will make sure the connecting arms always disappear behind the book image.

The 3 Feature boxesGraphic 2: The Three Feature Boxes

As these cover promos only have a lifespan of a couple weeks, I took the simplest option here and set the three feature boxes up as a single graphic, although in a perfect world I’d have made them a list.

I want this image to stay on the right-hand side of the container, so I’ve positioned it right:2%.

Like the book image, I’ve moved it to the front of our stack (z-index:90) and set its image dimensions to the default (111x160px) to keep it sharp and clear.

The stretchy graphicGraphic 3: The Connecting Arms

This, of course, is our stretchy graphic. It’s nothing more than a transparent PNG8 with some pinkish dotted lines. I added some fake soft shadows to give it a touch more depth.

The important point is to keep this graphic relatively plain and raw from the start. If we make it a bit chunky to begin with, stretching it out of shape can’t do all that much damage to it.

Firstly I’ve positioned this left:56%, so its left-hand side should always tuck in behind the book image (which was left:55%), regardless of the page width. I’ve also set the z-index for this graphic to 85, so it should never be in front of either the book or the boxes.

Next, I set the width of this connecting graphic to width:30%. This is 30% of the containing DIV, so the graphic will stretch and contract as its container does. The graphic’s right-hand edge tucks in nicely behind the feature boxes.

There’s no magical method for working out this percentage (30%) — it just takes a bit of trial and error. I set a temporary border on the stretchy graphic while I tweaked it, which helped to makes things clearer.

As you can see, the connecting arms certainly do distort as they stretch, but it doesn’t seem to be damaging to the overall result — to my eye at least.

The Wrap-up

If you like this effect, to my mind there are two challenges you’ll have to contend with. The first challenge is a technical one.

IE7 is happy to set your image width at 30% on page load, but it steadfastly refuses to automatically recalculate that width if you resize your browser window. Reloading the page will reset the width, but I don’t know of any way of forcing IE7 to recalculate the width on the fly.

Strangely, for all it’s other issues, IE6 will scale the image correctly, so this is clearly a new bug.

The second challenge is simply finding a plausible situation in which to use this technique. I’d certainly be keen to see any variations on the theme that you might come up with.

Paul O’Brien has suggested a fix for the IE7 refresh bug. He writes:

Regarding your stretchy images article the fix for IE7 is simply to wrap the image in a span and apply the measurements to the span and make the image 100% width and height. I always do it this way and it seems to work without problems :)

e.g.

 
div#promo-b div span#stretch {
 position:absolute;
 top:.5em;
 left:56%;
 z-index:85;
 width:30%;
 height:150px
}
div#promo-b div span#stretch img {
width:100%;
height:100%;
}


<span id="stretch"  >
<img src="http://www.sitepoint.com/images/books/design1/design1-stretch2.png" alt="" /></span>

Here’s an example of Paul’s code in action.

Sponsors