Image Placement vs. Image Replacement

This article was first published on tjkdesign.com (06-16-2005).

This technique is very versatile. Make sure you read the entire article to find out about the many different ways to implement the method. Also, I wrote a few other articles based on this solution:

What is FIR?

FIR is a standards-compliant technique that uses stylesheets and ordinary HTML to provide a visible image, usually consisting of text. The designer specifies, through CSS, that the image will display in most cases; if it should not display for some reason, the underlying structural HTML markup is supposed to take its place.

Joe Clark: Facts and Opinion About Fahrner Image Replacement

After spending some time reading about FIR, I thought it would be interesting to turn the debate on its head by reverting to the discarded <img /> element.
Please read on...

FIR factor

The various successors to the original Fahrner Image Replacement method have explored many different techniques. It seems that no stone has been left unturned by designers attempting to enhance the method. To achieve this goal they have tried all sorts of CSS attributes (display, overflow, text-indent, visibility, z-index, line-height), and structural hacks (empty span element). They even gave JavaScript (JS) a shot.

In my experience, however, all these techniques fail on some level with regard to various User Agents and their individual specificities:

Moreover, browser configurations play a role:

Whichever technique is employed it must be flexible enough to deal with the following:

  1. Show the image or, at the very least, the text it is meant to replace in any visual browser
  2. Make that text accessible by assistive devices (screen readers)

Whichever technique is employed, it must also successfully address these additional challenges:

  1. Avoid the simultaneous rendering of both text and image.
  2. Prevent text from leakage visibility regardless of user's text-size settings (e.g. text appearing beneath an image).
  3. Do so without use of "hacks".

I believe that I have found a plain and simple solution that not only addresses the points above, but further challenges as well, by using the very element everyone was trying to avoid in the first place - the <img /> element!

FIR less

The primary purpose of any Image Replacement technique is, as the name suggests, to replace text with an image to convey the same information, but in an aesthetically pleasing way.

Unfortunately, because most of these techniques rely on background images, the text ends up on top of the "stack". The challenge then becomes to somehow make that text disappear.

If we start by placing an image before text in a heading:

<h1>
    <img src="/img/helloworld.gif" alt="" />
    Hello World
</h1>

Then, this simple CSS rule could make the text portion vanish.

h1 img {
    position: absolute;
}

See example 1

Challenges we overcame:

Challenges remaining:

Next step:

Ensure that the text always remains within the boundaries of the image (NN6 included) and below the image (Opera 6).

Use the overflow, z-index and position properties keeping the exact same markup.

h1 {
    height: 28px;
    width: 207px;
    overflow: hidden;
    position: relative;
}
h1 img {
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
}

The width and height here are set to match the dimensions of the image.

The 2 position declarations are for NN6 (the first one is to make sure the browser positions the image in relation to the heading). Unfortunately, fixing NN6 breaks Opera 6 (it changes the stack order and places the text on top of the image). So we're using z-index to make sure Opera 6 hides the text behind the image. Of course, this last fix comes with its own issue, because it also makes this browser drop the image by a few pixels in this more advanced solution.

See example 2

Challenges we overcame:

Challenges remaining:

FIR no more!

Next steps:

If we keep moving away from the original method, we can actually resolve all issues at once.

We now use a transparent image (using a 1px * 1px image gives the element a minuscule footprint):

<h1>
    <img src="/img/clear.gif" alt="" />
    Hello World
</h1>

There is no longer a need to style the heading. Instead, we can focus on the image itself. The whole concept involves using the boundaries of the image as a flexible "window" to frame a rather large background image.

Based on that above, this is our new CSS rules:

h1 {
    position: relative;
    font-size: 1em;
}
h1 img {
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
    width: 538px;
    height: 1.7em;
    min-height: 28px;
    background: url(/img/helloworld.gif) no-repeat;
    border: 1px dotted red
}

How does it work?

We have set the dimensions for the image to create a flexible window. The width is fixed to prevent a few potential problems such as the spawning of a horizontal scrollbar or having to use min-width (that MSIE does not support). As the height is fluid, it will adjust gradually to match any change in text-size.

Because the image we used is 538px by 295px, the text in our heading will need to be larger than these dimensions before appearing from beneath the image.

If you do not care for Opera 6, do not hesitate to omit the z-index declaration.

See example 3

The black dotted border around the image(s) in the example pages is to give a better idea of the size of the picture that is used, while the red dotted border is to show the boundaries of the image element that is sized through the CSS rule.

Challenges we overcame:

Do you want an anchor with that?

If you include an anchor in the heading, then there is no need for an image element. This would be your (X)HTML markup:

<h1>
    <a title="Take me home!" href="/"></a>
    Company Name
</h1>

CSS declarations are identicals, only the selectors change:

h1 {
    position: relative;
}
h1 a {
    z-index: 1;
    position: absolute;
    top: 0;
    left: 0;
    width: 538px;
    height: 1.7em;
    min-height: 28px;
    background: url(/img/helloworld.gif) no-repeat;
    border: 1px dotted red;
    font-size: 1em;
}

Give it a try: example 4

And think of named anchors too:

<h1>
    <a id="topOfPage" name="topOfPage"></a>
    Company Name
</h1>

In my opinion the above solution is perfect for an image at the very top of a document. And this is extra clean markup that should make every standards zealot out there happy.

Final check:

I believe this method resolves many "problems":

As we are using an <img /> element, we have access to the title and alt attributes. By leaving out the title attribute and setting an empty value for alt we avoid some redundant information for users of screen readers when the document is read aloud. But, nonetheless, I am sure some people would find a good reason to use these attributes' values :-)

When using a real image (vs. a background image) the user doesn't experience flickering in MSIE when hovering over the element.

It is important to note that this method uses all the necessary elements. In short, it does not rely on any structural hack.

Pushing the envelope

Images rollovers:
An anchor is all that we need (no image element there). See example 4
It's a post from Richard Czeiger on the CSS-D list that gave me the idea.
Making the image scalable like the sIFR method does:
Slightly limited, but see example 5

With this method, one can style a group of elements without having to rely on div or class selectors. This is possible because the path to the image is part of the markup, not an attribute's value in the Stylesheet.

Another advantage of this technique is that the images, like in example 5, may be printed.

Replacing one image with another in media-specific instances.

Aaron Gustafson came up with a nice little trick that can also be used with the method discussed here. It is called iIR, it stands for img Image Replacement.

More on FIR

For further reading on the subject of FIR, visit the following URIs:

Techniques that go way beyond the call

2 amazing techniques to help you go "dynamic":