Hi, I’m Jeff Sarmiento, a web designer from
Toronto, Canada and I enjoy making smokin’ websites.

jQuery Image Replacement


While I was building this website I ran into the question of whether or not to use an image replacement technique for its graphical headers. I wanted a technique that kept my web pages accessible, search engine friendly and of course awesome looking. Here is a simple image replacement technique that I whipped up which uses jQuery to replace text with an image. Example and code below:

Bomb Diggity

$(document).ready(function() {
  if($('#logo')[0].offsetWidth == 288) {
    $('h2.img').each(function() {
      string = $(this).text();
      filename = string.toLowerCase().replace(/ /g, '-').replace(/([^0-9a-z-])/g,'');
      $(this).html('<img src="/images/' + filename + '.gif" alt="' + string + '" />');

The code uses jQuery to match all <h2> elements on the page that have the class “img”. Then for each matched element, it puts its text contents into a string, formats the string (I’ll explain why in a bit), then replaces the text with an image. The string is then used as the file name for the image that’s inserted. Sorry if that’s confusing but here is what’s going on:

<h2>Bomb Diggity</h2>

The above code is being replaced with this:

<h2><img src="/images/bomb-diggity.gif" alt="Bomb Diggity" /></h2>

I format the string to something that works with the file naming convention of my website by converting the string to lower case, replacing spaces with dashes and only allowing alphanumeric characters. You can tailor this to the file naming convention of your website.

The last step is to only run the image replacement if images are enabled. I did this by wrapping the image replacement code in an if statement that checks the offsetWidth of an existing image on that page, in this case my logo. If the value of offsetWidth does not equal the width of the image on the page, it assumes that images are turned off. The image replacement does not happen and the html header shows as normal.

Please note that this technique was made for my website and works perfectly for how I needed image replacement to work for my website. It may not be suitable for your website or you may prefer another image replacement technique. But if this method works for you, great!


June 8/08 at 11:04 pm

I’ve used something like that in an older site I did. I never thought about the offsetWidth to determine if images are enabled. Really slick! <3 jQuery.

June 9/08 at 5:48 am
Bruce Alrighty:

Nice script and I am loving the site design.
Just thought I would let you know the link on the about page for Textmate is incorrect. The correct link is http://macromates.com/ not http://www.textmate.com/.

June 9/08 at 10:31 am

Or you could just do without javascript entirely — just give the h2 a width, height, and a background image. To hide the text, do “text-align: -1000em” (see my site’s logo for an example)

June 9/08 at 11:25 am

Beautiful template!

June 9/08 at 11:39 am

use css property text-indent

June 9/08 at 11:45 am

Great tutorial, can’t wait to try it out!

June 9/08 at 12:59 pm

Thanks for the comments guys.

Jordan: I <3 jQuery also

pistachio & KAC: I wanted to come up with a method that I hope keeps my site accessible to screen readers and visitors with images turned off. By displacing the text somewhere off the screen, screen readers do not pick up the text. And with images turned off users see nothing.

I also did not want to have to create a CSS declaration for each header. For example:

#header1 { background: url(header1.gif) }
#header2 { background: url(header2.gif) }
#header3 { background: url(header3.gif) }

Less code is always good :)

Sorry I should have made these points a little more clear in my initial post.

June 9/08 at 7:57 pm

Hey Jeff,

As far as I know, using text-indent does not affect screen readers. using ‘display: none’ will though.

June 9/08 at 11:25 pm

Steven: Looks like you’re right, text-indent should not affect screen readers. But that still leaves the issue of nothing showing if images are disabled. Since this can be solved using javascript, why not use javascript to make image replacement happen easier.

June 12/08 at 3:42 pm

bomb diggity indeed!


June 12/08 at 4:57 pm

Although I think the text-indent phark method is still my preferred method (accessible – but nothing shows up when images are disabled), I see the benefits of this.
But if I were you I would abstract it, a little:

function imageReplace(selector) {
$(selector).each(function() {
string = $(this).text();
filename = string.toLowerCase().replace(/ /g, '-').replace(/([^0-9a-z-])/g,'');

This way, you could call it for multiple replacements across multiple selectors. You could even add src location and image filetype as arguments to the function.

June 12/08 at 6:13 pm

Hello Jeff!

Sorry for this offtopic but i’ve been trying to find the name of the font you use in the menu (and comments/leave a comment -boxes). Would you mind sharing it? :)

btw. i love this layout!

– Antti

June 13/08 at 3:22 pm

@Johs: Thanks!

@Mark Wunsch: Good stuff. My code works how I need it to for my website so far. But your changes make total sense. Others may need to modify or change the code so it works best for their website.

As a side note jQuery can also be used to match multiple selectors like so:

$('selector1, selector2')...

@Antti: font used is ITC Avant Garde Gothic

June 14/08 at 6:10 pm

You could use
"<h2><span>Bomb Diggity</span></h2>"
and set a background image, height, and width for h2.

Then, in your CSS:
"h2 span{ display: none;}"

June 14/08 at 8:23 pm

trendbreakr: You fail to see the benefits of using Jeff’s technique.
– no need for all the css declarations
– easier to call the replacement
– no unnecessary span’s
– shows text if images are disabled
– accessible to screen readers

June 17/08 at 7:01 am

Hi! I just found your site recently and I’m really loving your designs. I just wanted to ask, why not use sIFR? It seems to achieve the same thing.

June 17/08 at 6:17 pm

Very clever.

Nice site resource, I’m bookmarking you now.

June 17/08 at 9:09 pm

@Deanna: Thanks. sIFR was an option for me but since I was already using the jQuery framework on my site I decided to quickly come up with something using jQuery.

@Pete: Thanks Pete.

December 3/08 at 1:57 am

Freakin’ sweet! Thanks for this, it’s helped me solve a couple of big riddles I’ve been fighting with of late.

December 5/08 at 8:23 am

There is an issue with sIFR, firstly those that don’t have flash will essenitaly get prompted for every instance that a flash header is used — which can be very annoying.

The second issue is that screen reader browsers (I believe this happens with JAWS as an example) get stuck in flash files and the user has to close the browser completely. So the first flash header they hit they can get no further and have to restart the browser. Not great…

December 5/08 at 6:38 pm

@Zoe: No problem. Glad this post was of use to you.

@Ed: Thanks for posting your findings. I haven’t used sIFR much yet but it’s good to hear what kind of issues other people are encountering.

December 27/08 at 6:51 pm

nicely done…

Pure javascript, fully accessible, no css bloats needed, self contained.

As far as Sifr goes… I would advise against using sifr as much as possible. You still need flash to run sifr, and sifr is a whip to get working correctly…then you have all the little things that sifr chokes on. Using this little script as opposed to sifr is a no-brainer, as long as you’re willing to save out all of those textual images.

December 28/08 at 10:43 pm

Thanks Dan. I agree, it does take a bit to get sifr going correctly. And I don’t mind saving out all the textual images, let’s me get more creative with the headers.

February 25/09 at 2:30 am

Its nice…..

March 7/09 at 8:11 am

I’ve just one question regarding your jquery technique: Do you need to create all your graphical headers by hand or is there a script in wordpress which can create the files with the desired filenames and save them, so that the jquery script just needs to pick it up? You could alternatively use imagemagick to create the desired images on the fly, but I don’t know if thats accessible at all.

March 10/09 at 9:52 am

Hey Portfoleo, yes I create all the graphical headers by hand. I’ve never heard of a WordPress script or plugin that does this but I’m sure there are some PHP scripts. Yes ImageMagick can be used and it would be just as accessible. Cheers.

May 9/09 at 2:29 pm

[…] this: jQuery Image Replacement Thinking this looks like a good option. Any […]

June 17/09 at 6:58 pm

I really love this technique for image replacement.

However, with absolutely no disrespect, it points out an accessibility problem with your site when images are turned off.

In the, fairly unlikely, event that your images are not available you have very dark text displaying on a dark background.

July 27/09 at 3:45 pm

Awesome technique, this has come in really helpful implementing a custom navigation in SharePoint!

Thanks a lot 😀

February 3/10 at 6:16 am

Would somebody make a bit clearer the selectors thing? I’m not a programmer :) But I know how to use jQuery.
function imageReplace(selector) {
$(selector).each(function() {
string = $(this).text();
filename = string.toLowerCase().replace(/ /g, ‘-‘).replace(/([^0-9a-z-])/g,”);
Can you replace the selectors here with real example?

Or if you could place this:
$(‘selector1, selector2’)…

in your real example http://www.jeffsarmiento.com/2008/06/05/jquery-image-replacement/
so I can understand how to fix things.
What I want to achieve is to replace all h2 headers with images one h1 header as well.

Thanks in advance.

May 11/10 at 10:29 am

Great technique. I implemented it succesfully for a new site that I’m making. Only one thing… I was wondering if it is possible to include a hover effect for a different image?

April 29/11 at 11:44 pm

pistachio: i agree with your post.
leave out jquery and use this text-indent:-9999px;
but you have to have a width and height.
also a background:url ( header.png ) 0 0 no-repeat;

why using display:none isnt wise:
search engines will not index that header for your well written content.

happy coding


August 9/11 at 12:01 pm

Does anyone have any comments on using:

– Google fonts: google.com/webfonts#ChoosePlace:select
– cufon: http://cufon.shoqolate.com/generate/


to the top