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.

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • Christian Watson

    It can be a useful technique for a background image to a site. See this site for an example (scroll to the bottom and resize the page).

  • php_penguin

    “super wide” is 1440?? That is the standard wide-screen resolution these days…

    This seems like a bold step backwards – the level of chopping and positioning involved makes me think that it is way too complicated for what it achieves.

  • http://www.sitepoint.com AlexW

    It can be a useful technique for a background image to a site. See this site for an example (scroll to the bottom and resize the page).

    You’ve got a nice effect there with the centered background and it’s an image that tiles really well. Nice.

  • http://www.sitepoint.com AlexW

    “super wide” is 1440?? That is the standard wide-screen resolution these days…

    It might be standard for we who code and design for a living, but it’s not so common elsewhere. In fact, predictable screen dimensions are one of the few areas where you might look at 5 years ago at as ‘the golden era’. At that time the where only really 3 screens to consider — most users were at 800×600, with a smaller percentage either 640×480 or 1024×768. No-one genuinely expected to be able to view your site on a Palm or phone.

    Now we have to expect some users to be using 1600+px wide monitors, but I know I still use a 800×600 laptop in the kitchen at home. Safari in the iPhone is locked at the equivalent of 980px unzoomed, and it’s numbers are likely to double by Christmas morning.

    There are only likely to be more of these zoomable, screen width-limited devices in the coming year. People have been talking about mobile web browsing for 10 years, but people are actually starting to do it now.

    Screen width is getting more slightly variable every day. It’s a no-brainer if you’ve got reams of text to fill the space, but what are the alternatives if you haven’t?

  • http://www.darrensdirectory.com Darren884

    THis is so cool I didn’t know this was possible!

  • SMASHINGAPPS.COM

    Its a great article.

  • 3iTraffic.com

    Thanks for the graphic tips. Here’s what I’ve done with my graphic headers on my site 3i Traffic Exchange.

    There are many things you can do with stretching graphics to fit screen size.

    You just have to have your four corner graphics, and your two top/bottom and side graphics setup as a single pixel wide or tall graphic depending on whether its the top/bottom or sides.

    The second slightlier tricky part is then creating your web pages tables and css style file to fit your graphics and the design that your looking for.

    Last but not least, use a hex color picker and match the color from your graphics inside side, not to sound redundant. But you match that color for the background. Then your header or your whole graphical page can resize.

  • http://www.sitepoint.com AlexW

    Your graphics aren’t stretching, your table is, and using a table to accomplish that is considered less than best practice now. As is, placing your left and right header images inline, rather than a background.

  • A guy…

    WoW! seems like a lot of work for one image! NOT WORTH IT! too complicated…that time would be better spent developing the site rather than setting up an image to stretch…

  • Xaner

    It is a nice way to set background image to a site and it is very useful to set like the method mentioned in the article. But still it is complicated method rather then stretching the image.

    XanerSoft Technology

  • http://www.webtechnepal.com

    nice article

  • http://www.artexstudios.com James Gober

    very interesting article, I am amused by this technique actually I cant wait to play around with it.. thanks!

  • Mark.Cate @ shaw.ca

    A great inline fix.
    IE7 has no problem resizing the imager as the window resizes.

    HOWEVER!!!

    Resizing a background image using percent is a whole other conundrum.
    http://www.cssplay.co.uk/layouts/background.html
    Sure, layers are a great trick.

    QUESTION???

    How do you resize a CSS faux column background image?
    Will the genius with a solution please email same to mark.cate@shaw.ca

  • http://www.sitepoint.com AlexW

    Thanks for pointing that out, Mark.

    Wasn’t aware that backgrounds were resizable on the HTML and Body elements. Not exactly sure what yet, but I’m sure that will be useful for something. I need to have a think about where.

  • Kat

    wildgasmasks.com/wgm2/

    That has been my obstacl of this week. Your posting is encouraging that there is a way out of this. However, my image is a bit busier than the example you used and might not work. What can be done to make my images be a particular percentage value but prevent them from stretching too far? In this example the 2 corner images are made for 800×600 to 1200×800 layouts.

  • Deep

    But i want to strech background-image in a row only….
    what to do..?

  • Anonymous

    great concept, but quite a bit of work. someone would have to pay up the yin-yang for that!

  • Tom Davis

    “super wide” is 1440?? That is the standard wide-screen resolution these days…

    It is also the case, that people who have large screens, generally do not keep browser windows stretched to fill the entire screen.

  • http://www.meroblog.net

    it’s great. i’m use always css ………