Using background-image to replace text

Please note: The original technique (FIR) described in the body of this article is no longer recommended for use, as it makes the hidden text completely inaccessible for certain screen readers. Instead, see one of the alternative techniques mentioned at the end of the article under “Important Notes“.

This tutorial assumes a base-level knowledge of CSS, but not much more. Beyond that, it also assumes care will be taken to use these methods fairly and responsibly with well-structured markup.


Do you still crave the typographic control of creating headlines and decorative type with images instead of pure HTML text? Even with all the options we have for styling text with CSS, sometimes there’s just nothing that beats the indulgence of opening up Adobe Photoshop, then setting type in your favorite font at just the right size, kerning, and tracking. You know if you save it as an image and place it on a webpage, anyone with an image-enabled browser will see your typographic mastery just as you intended. Right?

But we’ve been beaten over the head so many times with preaching that claims using images for Web type will send us sliding straight to hell. So much so, we’ve dropped our visual standards and given up on the idea that type on the Web can ever be beautiful again. That is, until CSS font downloading is perfected and reliable many years from now.

We’ve been taught images aren’t as accessible as pure marked-up HTML text. This is especially true for assistive browsing software and small-screen devices. So we feel guilty using images for type. Images don’t show up in text-only browsers like Lynx, nor in browsers where users disable image rendering. Even if we’re responsible, always including equivalent alt attributes for each image tag, search robots often index meta data (like alt and title) differently than pure HTML text. This is understandable if we consider the logical importance of heading text when it’s appropriately marked up inside <hn></hn> tags. We won’t even touch on file size problems and download times caused by excessive image use.

Let’s put all that knowledge on hold for a moment. Images aren’t that bad, are they? With a few simple style tricks and a little cautious planning and testing, type on the Web can be guiltlessly beautiful and equally accessible (see notes below) and perfectly indexable, all at the same time. It’s time to spread those wings again.

The Concept

In principle, the concept is very simple. We write a short string of text (eg. “Hello world!”) and surround it with two sets of basic HTML tags. Then we use CSS to hide the HTML text and display a background image containing the exact same words instead of the original text. That’s it. Replacing text with an image is no more complicated than this.

Before we write any CSS, let’s start with some basic markup. Imagine we have a simple HTML snippet like the following:

  <span>Hello world!</span>

Of course we could apply style directly to that text. But we want more drama and finesse than any font-family or text-transform property can ever bring us. We want flourish. After all, if we’re saying “Hello!” to the world, we might as well do it with panache, right?

We pick out the perfect typeface for our worldly salutation: Shelley Allegro. A well-known script face in the design world, we discover Shelley has just the right flair to win the hearts of millions as we say Hello. We guess this font may only be available on 1.65% of the computer systems out there. So we take the time to create an image representing the same Hello message. The image will display our message in Shelley Allegro in every image-enabled browser, regardless of whether the font is installed on that system:

Hello world!

We take note of the image height, (35 pixels) since it will be useful a bit later.

So we have some HTML, a glorious text message, and one extraneous image. What do we do with them? Let’s roll up our sleeves and use a little style to replace the text with our new image.

Fahrner Image Replacement (FIR)

This method for replacing text with an image is named for Todd Fahrner, one of the persons originally credited with the idea. You may wonder why there are two sets of tags surrounding our Hello message in the HTML above. A div and a span. Technically the two tags could be anything. In fact, your custom solution may require something a bit more semantic. But we’ll choose these two generic wrappers for this example.

The CSS which executes the swap consists of two simple rules. The first uses background properties to pull our image into the background of the div:

div {

Note the height property in that rule. It matches the actual height of our image, ensuring the div is tall enough to display all of our image, yet takes up no more height than necessary. The background-repeat property ensures the image only appears once, instead of tiling across the width of our browser window.

The only remaining task is hiding the raw text which we left in our HTML. This is where span comes in. We need a second element so we can address it separately. Hiding the text is easy:

span {display:none;}

Combine those two rules with the HTML we wrote earlier, and we end up with a simple example. So simple, we wonder why it’s taken all this text so far to explain it?

Of course, we’d never leave our markup that simple. Nor would we likely be able to continue using such elementary style rules. Otherwise, every div we use would contain our “Hello world!” background image, and anything we place inside <span></span> tags would magically disappear.

Let’s move on to a few real-world examples.

Example 1: Page Titles

One example of text-replacement is readily available on many of the main pages of Notice the primary titles for each section or page (ie.: the words “Recent Log Entries” on the front page) They aren’t created by clever font-styling rules in the CSS. Those are images. Lovingly crafted to match the typeface of the logo. Matted to appropriate colors matching the background on which each is placed. It’s a subtle effect, but one that’s part of this site’s identity.

If we view the source, or toggle the CSS off, we see the title image is not part of the markup for that page. In fact, where most of us probably see an image, the markup uses simple <h1>‘s and pure HTML text to label that page and proclaim the title’s prominence and hierarchy in the document structure.

Screen readers, small-screen devices, and indexing robots will should* ignore any screen stylesheets, getting the pure text marked up as a simple <h1>.

One method of matching images to specific pages is to base the title image on the section in which it lives. Each body could be given an id or class unique to that section. Through the use of descendant selectors, each <h1> could be tied to an appropriate image based on the class of the body that contains it. But each section may contain more than one type of page, and we may want a more appropriate title for subpages of each section.

Instead, it may be wiser to assign each title a unique id matching or abbreviating the words it represents. For example, the Recent Log Entries title on stopdesign’s front page is assigned an id of “t-reclog“. The “t-” prefix is added to help create values which won’t be accidentally repeated in other element id values. “t-” always stands for title in this case. This id makes the markup a little redundant, but allows for the greatest flexibility in assigning any title image to any page.

Each replaced title needs a couple simple style properties assigned to it which are common to all replaced titles. In addition to the id, each title which needs to be “swapped” with an image is given a class of “swap“. The swap class exists so the same properties can be applied to all replaced titles without having to repeat those common properties in every unique title id rule. Alternatively, it avoids the need to specify every unique id appearing throughout the site just to create one rule of common properties. The application of the swap class ensures only those <h1>‘s possessing class="swap" get setup for replacement. Other non-replaced <h1>‘s can exist elsewhere on the site without needing to create rules which override the swap rules. The class addition is a small sacrifice in markup purity for huge simplification gains in the CSS.

For replaced titles on, the common CSS looks like:

h1.swap {
h1.swap span {display:none;}

And unique id rules look like:

h1#t-recentlog {background-image:url("/img/title_reclog.gif");}
h1#t-articles {background-image:url("/img/title_articles.gif");}
h1#t-portfolio {background-image:url("/img/title_port.gif");}

For ease of editing and maintenance, all page title rules are were separated into a separate titles.css file, which is imported by a linked master screen.css file.

Example 2: Controlled Drop Caps

Ever wanted a special drop cap to decorate the first letter of a paragraph? Yet didn’t like the clunky form created by bumping that HTML letter up to 500% of normal font-size? What about using an image instead? Of course we wouldn’t want to change the way that paragraph were read or presented should the image not be displayed. If we employ a slight variation of the replace method demonstrated above, we can use almost any type of drop cap desired. For example, let’s once again call on our familiar typeface, Shelley Allegro, to create an “E” which starts this same paragraph:


We won’t want the first letter of the paragraph to be separated on its own line (as a div would do). In fact, let’s say we want absolutely no special emphasis to be added when stylesheets are not used to view or read this paragraph. In this case, we’ll use two sets of generic span‘s to markup the first letter of our paragraph:

<p><span class="dropcap"><span>E</span></span>ver wanted a ...

Remember the outer element is what we use to apply the background image. The inner element is what we use to hide the raw HTML text. In this example, we’ll also be floating the outer element so the rest of the paragraph wraps around our drop cap. We’ll also set the display property to “block” to ensure compatibility with the widest range of browsers (even though use of float should do this automatically). We create the following CSS:

span.dropcap {
span.dropcap span {display:none;}

The width and height in the first rule above are taken from the image dimensions. We’ve also applied a small right-side margin to pad our drop cap image. Combine the HTML and CSS, apply a small amount of style to the paragraph itself, and we have a simple drop cap example.

More Examples

Creative uses for text replacement are only limited by our imagination. Other possibilities might include:

  • Type-based logos and names
  • Site headers
  • Pull-quotes
  • Single-word substitution for cosmetic effect (like “and” or “vs.”)

The method may also be useful for changing themes with alternate stylesheets. Just as you could change colors and styling, an entirely different image could be used for each theme.

Responsible Replacement

This replacement method needs to be exercised with a certain amount of responsibility. Care should be taken in matching the text of each replacing image with the same raw text in the HTML. Otherwise, it wouldn’t be fair to give visitors seeing full-blown stylesheets different textual content than visitors seeing, hearing, or feeling content without the same stylesheet applied. The replacing image can alter type characteristics such as size, color, capitalization, or tightened word-spacing. But those stylistic decisions are made as part of the design process, and should not be applied to the HTML text itself. For example, sandwiching words together (removal of word-spacing, as in the title images) in the HTML would create unreadable gibberish for screen readers and braille clients. Thus, the HTML text should be spaced, capitalized, and spelled appropriately as if it were completely unstyled in the first place.

Several very important caveats and disadvantages of this method need to be mentioned:

First, although the method is better [than only including raw images] for search indexing robots, it hinders the ability to find the replaced text on the page when the user executes a “Find on this page” search, or when the user attempts to copy and paste the text.

Second, although it may be rare that images are disabled in a browser, but CSS remains enabled, in these cases, CSS will still hide the text, yet may be unable to display the images, resulting in an unintended blank space with no text showing at all. As stated, these cases should be rare: when one is disabled or not available, the other is often the same.

Third, image text is not overridable by the user: they will not be able to resize the text, nor alter its color or contrast to make it more legible (as is possible with raw text).

These disadvantages need to be carefully considered in determining if this method is acceptable in specific instances. If this method is employed, the caveats should also be taken into consideration as the images used are being designed. Small or low-contrast text within the image would be irresponsible. Color-blindness may be a huge issue to consider when choosing colors and values for the text and/or background.

And remember, too much (or incorrect use) of a good thing can always come back to bite and betray. When we experiment with this method, we use it sparingly and with much caution.

Browser Compatibility

Mac: Camino .7+, IE 5+, Mozilla, Netscape 6+, OmniWeb 4+, Opera 5+, Safari

Win: Firebird .6+, IE 5+, Mozilla, Netscape 6+, Opera 5+, Phoenix .5+

Important Notes

This method has been tested and proven to fail in several popular screen readers. See Joe Clark’s well-researched, thoughtfully-written piece at A List Apart: Facts and Opinion About Fahrner Image Replacement.

The findings Joe presents in his article obviously defeat the original intentions of the method itself: creation of a more flexible and accessible solution than a simple <img> with alt text. The flaw with this method is that it assumes text hidden using display:none gets hidden in visual browsers, but will still get read aloud by a screen reader. This is not the case in several screen readers, even if we specify the “screen” media type for our style sheet. Screen readers also pay attention to the screen media type, since they literally read from what’s displayed on screen. Most screen readers don’t support the “aural” media type, so there’s no benefit to specifying speak properties in an aural style sheet.

Some have suggested the use of visibility:hidden; instead of display:none;, but this also prevents the text from being read in most of the same screen readers. Current versions of JAWS — arguably the most widely used screen reader — will read text hidden with FIR. But judging from behavior of other screen readers, we should not rely on this being the case with future versions of JAWS.

As is true with any content-altering technique, the advantages and disadvantages should be carefully considered for each unique case before being implemented. Since this article was written, several alternative methods have surfaced, each with their own advantages. However, no methods have emerged as the “Holy Grail” of text/image replacement. Existing alternatives to FIR are listed below:

Leahy/Langridge Image Replacement (LIR)
This method eliminates the span by setting height of the parent element to 0 and overflow to hidden, which hides the text. Then it uses top padding to force the element to the height of the image in the background. Conceived at similar times by Seamus Leahy and Stuart Langridge.
Rundle’s Text-Indent Method
Mike Rundle devised a simple method of using the CSS text-indent property to shift contained text outside the visible element window.
Cover-up Method
Another method devised by both Petr Stanicek (a.k.a. “Pixy”) and Tom Gilder uses an empty span element to position a background image on top of the text, allowing the text to show up when images are turned off (or don’t load) in the browser.

For further reading on the subject of FIR, refer to the previously mentioned article, Facts and Opinion About Fahrner Image Replacement, and Dave Shea’s In Defense of Fahrner Image Replacement at Digital Web.