Grow your CSS skills. Land your dream job.

Nine Techniques for CSS Image Replacement

Published by Chris Coyier

CSS image replacement is a technique of replacing a text element (usually a header tag) with an image. An example of this would be including a logo on a page. You may want to use a <h1> tag and text for this for the accessibility and SEO benefits, but ideally you'd like to show your logo, not text.

Update (March 14, 2012). I've created a new page that now covers more image replacement techniques, including the more recent Scott Kellum Method and the HTML5BP Method. I'm calling it the CSS Image Replacement Museum.

Note that some of these techniques are very old. Web design in the early 2000's was a lot different than it is now, but there was still much thought being put into accessibility. Because of that, most of these techniques still hold up today. It is still very interesting to see all the thought and problem solving that was put into this. Also note that I tested all these FF2, Opera 9, Safari 3, and IE 6 and they all behaved identically (hard to believe, I know).

The report card consists of five major categories:

  • CSS ON / Images ON
    Represents browsers in their normal states. All techniques should pass this test, since that's the whole point.
  • CSS ON / Images OFF
    Represents browsing with regular stylesheets applied but images turned off. This is rare but a possibility (folks with bandwidth concerns...) This is the most difficult test. Since most of these techniques go to various lengths to hide text, when the images are turned off that means that nothing is displayed which ain't good. Displaying text only here is considered a pass.
  • CSS OFF / Images ON
    Represents browsing with no stylesheets being applied. Most techniques default to regular web text here which isn't exactly a fail, but since images may still be turned on, I don't consider it a pass either.
  • CSS OFF / Images OFF
    Represents browsing with both images turned off and no stylesheets applied. Defaulting to text here is considered a pass.
  • Extra Unnecessary Markup
    Having to add markup for the sole purpose of image replacement is not ideal. Does not achieve true separation from content and design.

Technique #1

<h1 id="technique-one">
  <span>CSS-Tricks</span>
</h1>
h1#technique-one {
  width: 250px;
  height: 25px;
  background-image: url(logo.gif);
}
h1#technique-one span {
  display: none;
}

report-card-1.png

More information: This technique is referred to as FIR or "Fahrner Image Replacement". Much has been written about this including an A List Apart article about it's problems with accessibility as well as an article from David Shea defending it. The premise here is to use a span to wrap the text inside the header and use that span to hide the text. It works, but using display: none will hide the text from screen readers (and presumably search bots, not good).

Technique #2

<h1 class="technique-two">
  CSS-Tricks
</h1>
h1.technique-two {
  width: 2350px; height: 75px;
  background: url("images/header-image.jpg") top right;
  margin: 0 0 0 -2000px;
}

report-card-2.png

More information: Radu Darvas is credited with this technique. Basically this technique creates a giant box that goes way off the screen to the left. The text, being left-justified, cannot be seen. The image is placed in the top left of this box. It works, but it has the common problem of failing with CSS ON / Images OFF. I can also see this giant box thing being a problem in more complex layouts, besides being just generally less efficient than some other techniques.

Technique #3

<h1 class="technique-three">
  CSS-Tricks
</h1>
h1.technique-three {
  width: 350px; 
  height: 75px;
  background: url("images/header-image.jpg");
  text-indent: -9999px;
}

report-card-3.png

More information: This technique is credited to Mike Rundle and referred to as the Phark Method. This is probably the most widely used technique today. At the time of this writing, it is certainly the one I use most often. There is even a T-Shirt based on this one (2nd up from the bottom. The premise is deliciously simple: replace block with background image, kick text off page with indent. It's effective and keeps screen readers happy. It only fails the elusive CSS ON / Images OFF issue. A variation on this technique is to use negative letter spacing instead, which purports to resolve problems with triggering huge unwanted scrollbars in some browsers.

Technique #4

<h1 class="technique-four">
  <a href="#">
    <img src="images/header-image.jpg" alt="CSS-Tricks" />
  </a>
</h1>
h1.technique-four {
	width: 350px; height: 75px;
	background: url("images/header-image.jpg");
	text-indent: -9999px;
}

report-card-4.png

More information: I'm not sure the origin of this technique, but it's basically an extension of the Phark technique. Instead of bumping text off the screen you are bumping an image off the screen. This has the distinct advantage of still showing an image when CSS is OFF and images are ON, and also has ALT text for 508 compliance. This technique still fails with CSS ON / Images OFF. I give credit to Volkan Görgülü for pointing out this is the technique that Smashing Magazine is using in their header. One concern over this technique is whether or not it is effective SEO, specifically, if ALT text is just as good as regular web text. An extension of this technique would be to include regular web text inside the anchor link as well. Both the text and the image would get bumped off the page with the text-indent and it would aliveate the SEO concerns, but then you'd get "double text" with both images OFF and CSS OFF.

Technique #5

<h1 class="technique-five">
  <img src="images/blank.gif" alt="CSS-Tricks" />
  <span>CSS-Tricks</span>
</h1>
h1.technique-five {
	width: 350px; height: 75px;
	background: url("images/header-image.jpg");
	}
	h1.technique-five span {
		display: none;
	}

report-card-51.png

More information: Radu Darvas is also credited with this technique. By including a single-pixel transparent GIF image to the markup, you can restore ALT text with images turned off. This allows text to be displayed with CSS ON / Images OFF (!). Very effective, but adding the shim GIF is quite the blow to semantics. Also, with both CSS and Images OFF you get "double text", meaning both the alt text and the regular header text.

Technique #6

<h1 class="technique-six">
  CSS-Tricks
</h1>
h1.technique-six {
	width: 350px;
	padding: 75px 0 0 0;
	height: 0;
	background: url("images/header-image.jpg") no-repeat;
	overflow: hidden;
}

More information: This technique is credited to simultaneous discovery by Seamus Leahy and Stuart Langridge. This technique creates a box which will render with a height generated solely by top padding. By setting overflow to hidden, text will automatically be hidden but the box will be properly sized for a background image. This is accessibility-friendly and fairly effective, but fails in the CSS OFF / Images ON test as well as requires a box model hack for older versions of IE.

Technique #7

<h1 class="technique-seven">
	<span>CSS-Tricks</span>
</h1>
h1.technique-seven {
	width: 350px; height: 75px;
	background: url("images/header-image.jpg") no-repeat;
	}
	h1.technique-seven span {
		display: block;
		width: 0;
		height: 0;
		overflow: hidden;
	}

report-card-7.png

More information: Credited to Leon Dwyer. This technique is able to hide the text by putting it inside a box 0px wide and 0px tall with hidden overflow. Because it doesn't use the display attribute to hide the text, it's safe for screen readers.

Technique #8

<h1 class="technique-eight">
  <span></span>CSS-Tricks
</h1>
h1.technique-eight {
	width: 350px; height: 75px;
	position: relative;
	}
	h1.technique-eight span {
		background: url("images/header-image.jpg");
		position: absolute;
		width: 100%;
		height: 100%;
	}

report-card-8.png

More information: This technique is credited to Levin Alexander. In this technique, instead of pushing the text off the page or otherwise hiding it, the background image just sits on top of the text. This is the only other technique besides #5 which passes the CSS ON / Images OFF test. One problem with this technique is that if your background image uses transparency, the text will show through. Also, while not included in the original writeup of this technique, I would suggest hiding the overflow so that if the text size is bumped up large enough that it breaks out of the box it won't show.

Technique #9

<h1 class="technique-nine">
  CSS-Tricks
</h1>
h1.technique-nine {
  width: 350px; height: 75px;
  background: url("images/header-image.jpg") no-repeat;
  font-size: 1px;
  color: white;
}

report-card-9.png

More information: This technique is credited to Russ Weakley. With this technique, simply setting the text to an ultra-tiny 1px size and matching it's color to the background color of the image, you don't even need to hide it. While this technique makes a lot of sense accessibility wise, it has it's own problems. Like most of the others, it doesn't work with CSS ON / Images OFF. Even at the 1px size, the text is still visible, so this will only work on flat color backgrounds where it can blend in perfectly. I also have my suspicions that there may be some SEO penalties for this, both for the very small font-size and for matching background-color and color.

Even more information...

  • As usual, there is also a javascript solution.
  • There is a technique for doing this with inline-blocks instead of blocks.
  • If the only reason you are using this is to change the font, you'd be better off using @font-face.
  • Google Webmaster Tools has an article about this which doesn't specifically cover image replacement but reading between the lines, it seems like a reasonable amount of usage of this technique will have no negatives.

Comments

  1. Permalink to comment#

    There is another IR technique which is the best then these because is most accessibly (IMHO): http://wellstyled.com/css-replace-text-by-image.html

  2. @Mac: That is technique #8 above. I agree that’s a pretty good one, but it’s got the extra markup thing going and the problem with transparent images.

  3. Permalink to comment#

    Nice reports ! Just one thing : All these technics won’t render anything when you print the document …

    I think the best way to insert an image into a document what should stay accessible is to use an element, CSS backgrounds are only dedicated to decorative stuff.

  4. Permalink to comment#

    I’m still inclined to go the JS route (with a CSS backup).

    Ultimately, most people need the WORDS not the IMAGES (unless we’re dealing in photography, which this doesn’t apply to).

    Great round-up and examples!

  5. Permalink to comment#

    I use this technique for my logos:

    HTML:

    <a id="logo" href="#" title="Home" rel="nofollow">
      <img src="images/logo.png"
    width="317" height="63" alt="Logo"/>
    </a>
    

    CSS:

    a#logo {
    	width: 232px;
    	height: 55px;
    	position: relative;
    	float:left;
    	}
    	a#logo span {
    		position: absolute;
    		background:url(../images/logo.jpg) no-repeat;
    		width: 100%;
    		height: 100%;
    }
    

    It passes all tests :)

  6. Permalink to comment#

    Excellent post. I’ve been looking into image replacement in depth recently. Dave Shea has a thorough article over at Mezzoblue that is worth looking at.

  7. Permalink to comment#

    whoops! I see that link is in the post. Still an excellent post Chris. Covers all the bases.

  8. Martijn
    Permalink to comment#

    Really nice techniques. Love this site!

  9. I like #8 and then prob #3. A slightly different method is the sIFR idea which is good besides the extra bloat of swf files…

  10. Mike Salkeld
    Permalink to comment#

    How about:

    <h1><img src=”image_print.png” alt=”Image”></h1>

    h1 {
    background:url(image_screen.jpg);
    }

    h1 img {
    visibility: hidden;
    }

    I use it frequently and it works well for me…

    Mike

  11. Nice compilation of techniques, thanks.

    Of course you could use the technique described by Alvin but if you want to separate content from presentation, is not correct to put an img tag pointing to the image title, because this image is presentation, not content.

    Plus, an alt text will never represents the real text replaced, it could be a combination of strong, em, spans, and so on. You can’t emulate a strong effect inside you alt text.

    My conclusion is, there’s no ultimate technique for now, but the best one is definitely #8, provided you don’t need transparent images…

  12. German readers might want to check my 2005/2006 article providing another comprehensive overview on image replacement methods as well. Hope you’re okay with this recommendation, Chris, it should mean some references for part II of your article anyway ;)

  13. Unless I’m missing something, #4 doesn’t appear to be used on Smashing Magazine and I really can’t see the benefit of it. I mean why replace an image in the HTML with a CSS bg-image? :?

    Very effective, but adding the shim GIF is quite the blow to semantics.

    For #5, adding a blank image with no alt text doesn’t really impact the semantics of the page at all as it’s not going to be seen or heard.

    #7 has a span in the CSS but it’s missing from the HTML so not sure how that one works.

    I personally use a modified version of the Gilder-Levin method but for things like company logos would put the image in the HTML instead as I believe a logo is actually graphical content.

    I’ve not come across any conclusive studies as to whether search engines give that much extra weight to text over alt text but my suspicion is there’s not much difference.

  14. @John: Thanks for pointing out #7, I fixed that, there should have been spans around the text. The reason I like #4 is because it maintains the image when CSS is turned off. Like I’ve mentioned before, just because someone turns CSS off doesn’t mean they want their images off too, and many of these techniques do exactly that. The reason you would be replacing the image might be because it’s a different image. The one in the markup might be on a white background while the CSS replacement image might be more in context with the rest of the site.

    Smashing Mag is using the “extended” version of #4, which includes regular web text also. The h1 tag replaces all that markup with a single background image. If you turn CSS on their page, you can see the logo remains, along with all the web text.

    <h1 class="logo"><a title="Smashing Magazine Homepage" href="http://www.smashingmagazine.com/"><img src="http://www.smashingmagazine.com/wp-content/themes/SM-theme/img/logo.gif&quot; width="229" height="83" alt="Smashing Magazine ~ we smash you with the information that will make your life easier. really." /></a><br /><a title="Smashing Magazine Homepage" href="http://www.smashingmagazine.com/">Smashing Magazine <em>we smash you with the information that will make your life easier. really.</em></a></h1>

  15. Mike Salkeld
    Permalink to comment#

    I’ve put a working sample of what I use up at:

    http://www.luminancedesign.co.uk/csstricks/index.html

    Let me know if I’m missing something here…

    Mike

  16. @Mike: That technique fails the CSS ON / Images OFF (nothing is displayed). Many of the techniques fail that one though, doesn’t mean it won’t work for your application.

  17. Permalink to comment#

    Thanks man! Very useful

  18. I typically use the Phark method, but I throw in “overflow: hidden;” to keep from running into the scrollbar issue and return the containing div to the specified width so everything looks kosher when I outline block-level elements with the Firefox developer toolbar.

  19. Hi Chris,
    I wrote a few articles about a technique that is not listed here. It relies on the IMG element, I believe it passes all the points of your report card and also allows the image to be printed.

  20. Thanks for Sharing

  21. @Chris:
    What method did you use to test these?
    I’m using XP Pro SP3 and Firefox 2.0.0.14 with the Web Developer 1.1.6 extension.
    And I came to different results that those posted above?!

    Anyone try an alternate jQuery method?
    I searched and located this site: http://www.texotela.co.uk/code/jquery/jQIR/

  22. Permalink to comment#

    Hi … great stuff.

    How about this:

    print("<p id="someid">Normal text<span>something that must be a img</span>rest of text </p>
    ");

    I’m trying all techniques but no one want work.

    Help – please !!!

  23. Chris
    Permalink to comment#

    Hi Chris,

    This is Chris. I was searching for image replacement techniques and this article was very helpful. I have only used image replacement once for a site and I didn’t even know I was using the Alexander Method.

    I want something where the text is still displayed with images off and this has worked for me but as you stated, this can’t be done with an image that has a transparent background.

    sigh As I am working on the re-design of my website and I am using a transparent bg. But anyway, thanks for the good article.

  24. Permalink to comment#

    Thanks for sharing!!

  25. Awesome breakdown of the different techniques, and very detailed. I do see the text-indent tactic used most often, but I often wonder how Google feels about it. It doesn’t seem too difficult to detect the probability of abuse, especially in the case of H tags.

  26. This is great, I will use this CSS technique with my websites. Always had trouble with image-issues… Coding text is so simple, with images I was always stuck.

    Thanks for the tips & you got a great website, just keep it goin’!

  27. Permalink to comment#

    Thanks man! Very useful

  28. Permalink to comment#

    Awesome breakdown of the different techniques, and very detailed. I do see the text-indent tactic used most often, but I often wonder how Google feels about it. It doesn’t seem too difficult to detect the probability of abuse, especially in the case of H tags.

  29. Erick
    Permalink to comment#

    Chris,
    Thank you for this article and for all of the video screen casts. Is there a method for having the replaced image be a link. I would like to have the logo in my header be a link back to home. I have tried #4 but can’t get it to work. Perhaps there is a better method that you could suggest to achieve my goal.

  30. Hey Chris, can we get some IDs on each entry in the Image Replacement Museum? It would make it easier to reference specific image replacement techniques in code docs, issues, etc.

    Thanks again for this resource!

  31. Kellum has a new technique that uses a blank, transparent webfont to hide the text. Quite ingenious indeed: http://scottkellum.com/2013/10/25/the-new-kellum-method.html

  32. Frederic
    Permalink to comment#

    Why not do it like this?

    HTML:
    <h1 class="replace">CSS Tricks</h1>

    CSS:
    h1.replace {
    display: block;
    background: url("images/header-image.jpg");
    width: 350px; height: 75px;
    padding-top: 75px;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    overflow: hidden;
    }

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".