Thursday 23 June 2011

How To Create Flexible Images And Media In CSS Layouts | Van SEO Design

How To Create Flexible Images And Media In CSS Layouts | Van SEO Design


How To Create Flexible Images And Media In CSS Layouts

Posted: 23 Jun 2011 07:30 AM PDT

A flexible layout isn’t all that flexible if some of the component parts are fixed. Text easily reflows as it’s container resizes, but what about images and other media? How do we make them flexible to keep our layout flexible?

Last week we talked about elastic layouts and flexible grids. Next week we’ll look at media queries. We’re building toward responsive layouts by discussing each of the 3 parts necessary for responsive design in a separate post.

All the credit here belongs to Ethan Marcotte and I recommend his post on flexible images. I also highly recommend Ethan’s new book on responsive design.

Also Richard Rutter has set up a page experimenting with flexible images using max-width that’s worth checking out.

Elastic bands

How to Create Flexible Images

Typically when adding an image to a web page we set a width and height using absolute measurements like ‘px’. Unfortunately this fixes the image size and is completely inflexible.

At one specific point the absolutely fixed image is probably the perfect size. However in all other cases it will either be too large or too small for the layout. Let’s consider the case where the image is larger than its container.

We already know how to keep elements from growing too large and that’s through the max-width property

 img { 	max-width: 100% } 

And with that one line of code we’ll prevent our images from ever being larger than their containers. And since we’ve set the measurement in % the image can resize itself as its container resizes.

If an image is larger than it’s container it will be scaled back to be the same size as the container. If the image is smaller than the container the image will be its default size.

Modern browsers are good at maintaining proportions so the image will resize well as the layout resizes. This works not only with images, but with video and other media. We can refine the above css to be:

 img, embed, object, video { 	max-width: 100% } 

And we’re done. This is all seeming too easy isn’t it? Unfortunately we’re not there yet. The above doesn’t quite work everywhere.

Internet Explorer 6 logo

Internet Explorer 6

First up is IE6, which probably isn’t any surprise. It may also not be much of a problem depending on your site. IE6 is finally falling out of use so it’s up to you whether or not it’s worth supporting.

IE6 doesn’t support max-width, but it treats the width property similar to max-width. The simple fix then is to use a conditional comment targeting IE6 and then set the width to 100%.

This will force all images to be the same size as the container. It works great if the image is larger than the container, but for images meant to be smaller like thumbnails and icons the images will scale up and usually not look too good.

We could go through the trouble of wrapping each of these smaller images inside its own container and set additional css on the containers, but that’s probably more work than it’s worth.

You can also apply a fix using Microsoft’s expression() property, though it usually takes some trial and error to get the values you need correct.

For my part I’ve stopped developing for IE6 unless specifically requested and paid for by a client. On this site IE6 use has dropped to less than ½%

Microsoft Windows logo

Windows

We’ve either taken care of IE6 or ignored it, but we’re still not done. Unfortunately Windows the platform doesn’t scale images as well as it could. Resized images can look pretty bad due to a bug in the operating system.

Fortunately while the issue is with the platform it only affects a few specific versions of browsers.

The browsers in question are Firefox 2, and IE 7 and below. The issue doesn’t affect other modern browsers. It also appears as though the bug has been fixed in IE7 so we’re actually down to IE6 and FF2 as browsers we need to find a workaround for.

The solution for IE6 (again should you choose to support it) is to use Microsoft’s AlphaImageLoader filter.

You may be familiar with AlphaImageLoader since it’s also used in a fix for transparent .pngs on IE. Since it’s Microsoft specific though it won’t work with FF2.

I’m willing to concede that we probably don’t need to support FF2 and as I said above I’ve stopped supporting IE6 as well.

Odds are you probably aren’t going to support either of them so instead of presenting details of the fix here I’ll once again point you to Ethan’s post on flexible images, which includes a javascript fix and a few more details about the issue and solution.

Textured background image of beach

Background Images

We’re close, but still not all the way to having flexible images everywhere. If you’ve noticed we’ve been talking about images directly in your html so far. What about background images declared in your css?

Vertically Repeated Images

A couple of weeks ago I posted 4 methods for creating equal height columns in css and the first of those methods was faux columns. In that method we set a fixed width background image on a container div and repeated it vertically to mimic the background behind the individual columns.

While in that post we used a fixed width image, the method can be extended to be a little more flexible, if we’re willing to apply a little math.

Faux columns background

Let’s use the image from the faux columns post (seen above) as an example. The image was 960px wide and transitioned at 340px from the left edge. First we’ll use the hopefully familiar formula we used to create elastic grids.

target &divide context = result

340px ÷ 960px = 35.4167%

Now we know where our transition point is located relative to the edge.

Next we’ll create a much larger background image than we’ll reasonably need and once again do the math in reverse to determine where we need to set that transition point.

Let’s create an image that’s 3000px wide.

target ÷ 3000px = 35.4167%

Doing the math our target becomes 1062.5 px. Since we need to use integer values in Photoshop we’ll round up to 1063 px.

Finally we’ll set the image using the css background-position property.

 background: url("background-image.png") repeat-y 35.4167% 0; 

Our image can now scale with our layout while our transition point will always remain where we want.

The above works for vertically repeating background images, but it’s not truly flexible in the sense that we’ve created a fixed width image, just one much larger than we think we’ll ever need.

We’ll be ok as long as the layout doesn’t get wider than the image, but that may not always be the case.

Horizontally Repeating Images

If you have a small image that you’re using as a repeating background there shouldn’t be any issue. The image will repeat to fill up its container regardless of size.

Assuming the image is small enough horizontally or represents something that only changes vertically (think gradient on a navigation bar), the worst case is being off a couple of px at the edge, which is unlikely to be noticed by most.

Background-Size

CSS3 has a property called background-size, which would be perfect, but at the moment it’s not supported well enough to use in practice.

Next week we’ll talk about media queries, which will let us set different images over a range of layout widths. In time the combination of media queries and background-size will be our solution, but sadly not today.

Overflow at derwent reservoir

Hiding Images with Overflow

Much of the time max-width alone will be enough to keep your layouts flexible. At times though your images won’t scale well because of the content of the image or perhaps it’s not really necessary to always show the entire image.

If we set overflow: hidden on a container around an image then as the container is resized smaller than the image, part of the image will be hidden. The image won’t be flexible, but it will preserve the integrity of your layout and allow it to remain flexible.

Most of the time max-width will be the better option, but depending on the content in the image it may also be ok to hide it instead of resizing it.

Image Replacement

There’s one last method which involves replacing images that might be useful when your image is complex enough that scaling it doesn’t work well and where hiding part of the image isn’t an option.

The solution is to use multiple images and serve different sized images under different conditions.

This is a server side method and instead of presenting it incorrectly here I’ll direct you to a post by Bryan Rieger on mobile image replacement with the details and even better a download with all the code you need.

Next week we’ll dive into media queries which also allow you to serve different images based on device and screen width among other things.

Colorful elastic bands

Summary

Being able to create flexible images is an important consideration when trying to create a flexible layout. What good is a flexible layout if the content inside forces the layout to be rigid?

For most cases all we need to do is set a max-width of 100% on our images (and media) to make them flexible. You’ll need a couple of fixes for IE6 and one for FF2 should you decide you need to support those browsers.

With vertically repeating background images we’ll create much larger images than necessary and use a little math to understand where to set transition points on the background-position property.

At times we can apply an overflow: hidden fix that will preserve the flexibility of our layout even if they don’t make our images any more flexible.

In time we’ll have browser support for the css3 background-resize property, but for now max-width: 100% and overflow: hidden should cover most cases.

Even with all of the above methods we don’t have a way to create flexible images 100% of the time. We are able to cover most practical cases and perhaps rethink our use of images in those few cases we can’t yet cover.

Next week we’ll continue with a discussion of media queries before wrapping up with some thoughts about responsive design.