::Stuff for the multi-spec coder;

Coding, formats, standards, and other practical things.

 Home  //  CSS Articles  //  CSS Image Techniques: Part 1 

<!-- CSS Articles

CSS Image Techniques: Part 1

When CSS-based designs were just starting to catch on, there was a tremendous focus on minimalistic designs that mostly utilized XHTML/HTML, and CSS. Two "things" took a hit back then, and both for the wrong reasons: The use of JavaScript, and bitmap images. From a purist's perspective, when markup is combined with CSS, and CSS alone, the browser renders the page using one 'vector', or aspect, of its abilities. After all, JavaScript makes the browser have to run a whole independent interpreter in order to execute the simplest of scripts, and it just introduces more browser incompatibilities. And images each load using separate http calls, so even if they're small downloads, they make it up in volume. Plus, they don't scale, so that places them outside the gates completely.
What we got was the 'Web 2.0 desolation', at least until people wised up a bit. For a short while, it seemed like every website you'd go to looked the same: There were two or three images at the most, many, many fonts, and vey big type for each and every paragraph heading. This was in-line with the "Blog Rush", so it even seemed to make sense for some sites to adopt this approach.
While it didn't take JavaScript long to make a comeback, both because designers and developers understood they were throwing away incredible functionality for no good reason, and because of the rise of Ajax. But images were different. Designers still thought of them as "clogging up the flow" of their carefully thought-out CSS designs. It took a while for designers to realize that they simply needed to rethink the way bitmap images were used, the same way they rethought how markup was used.

Still, to this day, the use of images in CSS-centric designs is light and, if I may use an artsy phrase, "undaring" (I'm not sure that's a word, actually... But you get my meaning). You have to specifically seek out certain kinds of web sites, like gaming sites or media sites to find more assertive use of images, and many of them do so wonderfully.
Using the right methods and techniques, you can streamline bitmap images into a CSS-based design, and avoid the perceived problems that shunted images to the side on so many web sites.

Reduce HTTP Calls - Using "Image Arrays"

When you place an image into a document using the IMG element, or as a background of an element, the browser makes an HTTP call to get the image from the server, whereever that may be. This enables bandwidth control since images may be placed at different locations than the document itself, and also the src of the image may actually call a server-side script. However, many times, all/most/many/several images on the page will originate from the same location. Remember that each HTTP call involves a comparatively long and involved "handshake" procedure, which doesn't care how large the image file size is. You many think you're saving space on the page by sprinkling many small images on it, but the user trying to load it will experience a longer load time the more images there are, even if each of them is a [2-digit]-bytes black-and-white icon.
The first technique I'll cover involves 'tiling' several images into a single image file, and having CSS crop the one you need from the batch. While the basic idea is the same, the implementation varies, so I'll go over several and expand on the reasons you might use one over the other. By the way, the term "Image Arrays" is a generic one, you'll often see it being referred to as "background-cropping" or "CSS Texture Mapping". If you search for more information on this particular technique, try searching for the properties involved rather than any specific technique name.

Take for example the following image:



It's basically four of the same icon, each in a different hue, one after the other, all placed in one image. The icons themselves are 50 pixels by 30 pixels, but combined the image (having four of the icons placed one after the other, vertically), is 50 by 120.
The goal is to get just one of these images out of the "array", so we're going to need a way to tell CSS to crop out an area from X1/Y1, to X2/Y2, essentially a selection rectangle within the image. We're going to do this using the background-image property, along with a few accomplices.

First, we'll create a class which all of the "image elements" (as you'll see, they won't actually be IMG elements) will share:

.arrow { display: block; width: 50px; height: 30px; background-image: url(images/bubble_arrow_quad.png); }

This is basically a class that turns a "neutral" element into a block-level element (if it's not already so), sets its width property value to 50px, its height property value to 30px, and finally gives it a background-image, in this case: bubble_arrow_quad.png.

Let's take some sample markup and see what we have so far:

<span class="arrow"></span>


Basically, this gives us a pseudo-image, with the first image in the 'queue' being displayed. This is only because we set its height to 30px, which means it wasn't able to 'spill' any additional icons into the drawing area, and limited its width to 50px, preventing it from repeating horizontally.
This is a very limited solution, however. We may want to place content to the right of the image, and while we can float it (we'll get to that later), it still doesn't solve the issue of switching between icons.

To solve this we add two more background properties: background-repeat, and background-position. We don't want the images to tile (repeat vertically or horizontally) here at all, so we're going assign the no-repeat value to background-repeat. This means that as the background-image, the bitmap will display only once, and only at the position we 'tell' it to appear in. This leads us to background-position, which allows us, among other things, to offset the image using an absolute number of pixels (rather than, for example, just assigning top as the property value).
Knowing this, we can use a mix of properties to "crop" just the area within the image that we want to display. Here's an example of how the CSS would look if it were all in one class:

.arrow_red { display: block; width: 50px; height: 30px; background-image: url(images/bubble_arrow_quad.png); background-repeat: no-repeat; background-position: 0px -30px; }


Using the same single SPAN element we used previously, here's what we get:


The background-position property value (of 0px -30px) told the renderer (in this case, the browser) to move the image 30 pixels upward (since the Y-axis on the monitor, and the document, starts at the top, and increases as you proceed downward). This meant that the image was moved to a point where the first icon was shifted by exactly its own height, upward, and since the area limited the height to 30 pixels, the second icon, also 30-pixels tall, is cropped perfectly within these limits.
Actually, the width property plays a less significant role now that the background-image will no longer tile in any direction. However, the SPAN does need to be large enough to show the image you want, otherwise the SPAN element itself will further crop the image.

Now that we have the basic ideas covered, let's go over a few practical aspects. First, that was a very large CSS class to have to make for each and every image. Instead, here's a better way to rearrange the CSS rules:

.arrow_icon { display: block; width: 50px; height: 30px; background-image: url(images/bubble_arrow_quad.png); background-repeat: no-repeat; } .ar_purple { background-position: 0px 0px; } .ar_red { background-position: 0px -30px; }

All of the common properties were placed into one class, and the background-position property, which determines the offset, and thus which icon is displayed, was placed in separate classes. This means that you could place, say, 10 icons (or sub-images) in one image file, and still be able to save up on markup. Speaking of markup, we now need to assign two classes to the SPAN element:

<span class="arrow_icon ar_red"></span> Some Text... <span class="arrow_icon ar_purple"></span>

Go forth, and render:

Some Text...

Cool, it's almost like images. Well, I did said almost. You'd be able to stack IMG elements horizontally. Lucky for us, we can always float:

<span class="arrow_icon ar_red" style="float:left;"></span> <span class="arrow_icon ar_purple" style="float:left;"></span> Some Text...

And we get:

Some Text...
If you don't have much experience with floating elements, check out the Floating Elements article, it'll especially come in handy later when dealing with additional floating methods.

Cropping X and Y

That first image was kind of a softball. All the cool kids know how to take advantage of cropping an image in both axes. There are several reasons for doing this: You may have images of different sizes and want to place all of them within one file, for example. If you only crop on one axis, you'd be saving a file with the largest possible width or height of the array of images you want to use. Also, there are compression elements that you may want to take advantage of in the PNG file format, like keeping images with the same background color in the same horizontal row, and then having several rows.
Whatever the reason, there actually isn't much more to this than what we've seen so far. Here's another example image:



This time, we have two rows of "icons", with 3 icons in each row. We'd of course like to separate them so we can use them individually around the document. We'll start with the common CSS class:

.icons { display: block; width: 40px; height: 40px; background-image: url(images/sixicons.png); background-repeat: no-repeat; }

You can deduce from this class that the width and height of each icon is 40 pixels, and that the image file name is sixicons.png. I didn't create a very challanging example this time for X/Y cropping in the sense that all of the sub-images are of the same size. As you'll see, however, even if they weren't, you'd still be using a simimlar (though not exact) technique.

First, let's crop the top-left icon:

.icon_1 { background-position: 0px 0px; }

The markup would be:

<span class="icons icon_1"></span>

Which would result in:


That was, of course, the easiest one. Now let's say we want the middle-bottom icon:

.icon_5 { background-position: -40px -40px; }

The image is shifted 40 pixels upward, and 40 pixels to the left (hence both values are negative), which means we move the cropping area 40 pixels right and down:


Let's see the CSS for all of the icons:

.icon_1 { background-position: 0px 0px; } .icon_2 { background-position: -40px 0px; } .icon_3 { background-position: -80px 0px; } .icon_4 { background-position: 0px -40px; } .icon_5 { background-position: -40px -40px; } .icon_6 { background-position: -80px -40px; }

Now for a proof of concept:

<span class="icons icon_1" style="float:left;"></span> &nbsp; - Icon No.1<br/> <span class="icons icon_2" style="float:left;"></span> &nbsp; - Icon No.2<br/> <span class="icons icon_3" style="float:left;"></span> &nbsp; - Icon No.3<br/> <span class="icons icon_4" style="float:left;"></span> &nbsp; - Icon No.4<br/> <span class="icons icon_5" style="float:left;"></span> &nbsp; - Icon No.5<br/> <span class="icons icon_6" style="float:left;"></span> &nbsp; - Icon No.6<br/>

That's kind of an odd way of spreading them around, but it makes for a neat way of showing that they're completely independant:

  - Icon No.1
  - Icon No.2
  - Icon No.3
  - Icon No.4
  - Icon No.5
  - Icon No.6


Keep in mind that these are large sub-images, relatively speaking. You could have 20-by-20 pixel sub-images, and place 15 of them in a single small image array. In the next installment of CSS Image Techniques, I'll expand more on image cropping, and see how it can be used other than just as a replacement of the IMG element.
In the meantime, if you haven't already, check out the Image File Formats article, as more and more elements of the individual image format properties will come into play.




Return to the CSS Articles section, or go the to Main page.





Looking for the old guiStuff?

It's still here, the old content didn't go anywhere.