Update 4/11/06: I’ve received some criticism on this post from people who assumed I was saying you should never use image tags in HTML. My bad for the misleading title, I’ve added to the title in parens to be more concise! For those that didn’t read the whole post, in the last paragraph I say that it’s fine to use HTML image tags for content, I just think it’s bad design to use image tags for style elements. Anyhow, thanks for all the feedback (postive and negative) and here’s the original post:
CSS offers us a lot of power to style and decorate our pages with images, however, replacing text with an image is one gap not well addressed by CSS such that you often see sites doing:
<a href=”/”><img alt=”Home” src=”home.gif”/></a>
which is obviously bad for 2 reasons:
1. It violates the separation of content and design by including a design element in your HTML
2. Your SEO will suffer because image alt tags don’t carry as much weight as real text
As a result a number of people have come up with clever image replacement techniques in CSS. It began in 2003 with the Fahrner Image Replacement technique (or Classic FIR), however, the technique I currently favor is the Mike Rundle’s Phark revised method which:
1. Works well cross browser (but be sure to test in IE 5 for possible issues if you’re still supporting it)
2. Works with a screen reader such as JAWS for accessibility
3. Works well for SEO (many techniques style the text with display:none which likely won’t work with the next generation of crawlers such as Google’s new Mozilla based crawler)
Taking the example above, the correct approach would be as follows:
<a id=”home” href=”/”>Home</a>
Then apply the Phark revised method via CSS:
background: url(/images/home.gif) no-repeat;
Here’s the result:
Now we’ve replaced the text with an image yet still kept the separation of content and design clean. I stated that it’s bad design to use image tags in your HTML but I’d like to qualify that, it’s fine if your “content” is an image such as a product photograph in a web catalog, a graph, or a headshot in your user profile. Also I think it’s fine to bail on image replacement if you start wasting a lot of time in CSS layout land, it’s just good to start with the clean text based approach first and use it until it becomes impractical.
I use the Rundle method often, but find that I also have to specify overflow: hidden to get it to work right in most browsers.
If web designer wants to have a secure job, this might be really a good approach. Nobody else can understand the code without hard digging into it.
The text-indent: -9000px; sounds very promised 🙂
While the goal is good, the method is stupid: This is abusing some technique (CSS/text-indent) for something it was definitely not designed for. This will cause more problems than it solves.
BTW: You should not trust anyone who asks questions like “Are you supporting $BROWSER version xx,yy?” I never used or tested with or designed for IE5, but I’m still “supporting” it. For sure. It’s a browser, it’s more or less compilant with some subset of web standards. If they break my site, I may or may not work around it, but I’m not going to break anything (on purpose), not even MSIE.
Jan and Sergey, I agree that image replacement is hack but I think when used appropriately it keeps the page cleaner. In reality you can design a great looking site that’s predominantly text based using background images and image decoration leaving the text visible. The only time you need to do image replacement is in those rare cases where for whatever reason you completely want to replace the text with an image and then it works very well while keeping the design cleanly separated from the content. I just hope a future version of CSS will natively support image replacement instead of forcing us to resort to these type of workarounds to have good separation of concerns.
It violates the separation of content and design by including a design element in your HTML
I have to disagree with this, too. What if your document contains an image? Compare this to an image embedded in some other XML document.
The way I see it, there’s a separation from design elements, and the actual content of your document. Say you have a page template, for example, with a logo header graphic. This is completely separate from an image that might be embedded as part of a document, e.g. a screenshot, map, etc.
In the case of a blog, I’m more apt to use the CSS image trick for template stuff, and then use img tags in the content of the posts. Conceptually, the template that the page is on is totally separate from the content that it houses.
This can be solved with a two-step view pattern. For example, say you had all of your blog posts marked up in some descriptive XML format. If you wanted to inline an image, you’d be forced to use a tag to describe the fact that an image belongs at that point in the document structure. With two-step view, you’d convert your descriptive XML format (to something like XHTML), and then merge it with the site template. Your end result is an HTML page, and your original source document correctly (and richly) describes the location of something like an inline/embedded image.
Tony, I completely agree with you and I guess I didn’t do a good enough job clarifying in my initial post because I think other people misunderstood me as well. Near the bottom of my post I say that it’s fine to use image tags for content. If your document contains an image that is content, not style so image tags are totally appropriate in that case.
🙂 It’s the details that count.
I’ve used this exact trick (text-indent: -9000px) myself a few times, but the worst niggle I have with it, is the focus lines which appear in Firefox (PC).
When a link using this technique is clicked, a momentary band of focus lines is visible across the screen from the link itself right to the far left of the screen (tracking the path of the negatively indented text) remaining visible until the browser or server responds and the new page loads. Apart from that minor visual niggle, it’s a great idea.
This site served as a reference.