Unobtrusive, cross-browser method to add icons to links

categories: front-end development, howto, jquery

There are lots of examples of using CSS to add filetype icons to links, but they all rely on advanced CSS selectors, which Internet Explorer 6 doesn't support.

If you're looking for a cross-browser method of adding filetype icons to links, you have a couple of choices: you can add a class name to all of your links and target that class name with CSS that IE6 can understand; or you can let Javascript add the links dynamically based on the extension it finds at the end of each URL. The class name method is fine if you don't mind adding the class to all of your links in your HTML, but the Javascript method will figure out which links get which icon automatically.

The Javascript/jQuery method

This uses my favorite Javascript library, jQuery; you'll need to include the library in your document, and then either put the icon-adding code in another file you include, or put it inline with your HTML. It's good practice to put all your jQuery code inside $.ready(), to be executed when the document is ready to be manipulated, but I've left that part out here for brevity.

Round 1: Because jQuery supports CSS1-3, you can mimic the CSS rule that wouldn't work in IE6:

 
$('a[href$=".doc"]').
  css({
    // use paddingLeft instead of padding-left;
    // jQuery (and Javascript) use camelCase
    // for CSS attributes instead of hyphenation
    paddingLeft: '18px',
    background: 'transparent url("word-doc.gif") no-repeat center left'
  });
 

Round 2: You could do one of these snippets for each file type, but with jQuery, you can take advantage of the $.each() utility method to do a loop, eliminating redundant code:

 
// first, create an object
// that contains information
// about how file extensions
// correspond to images
 
var fileTypes = {
  // extension: 'image file'
  doc: 'doc.gif',
  xls: 'xls.gif',
  pdf: 'pdf.gif'
};
 
// then, loop over the object
// using jQuery's $.each()
$.each(fileTypes, function(extension,image) {
  $('a[href$="' + extension + '"]').
    css({
      paddingLeft: '18px',
      background: 'transparent url("' + image + '") no-repeat center left'
    });
});
 

Round 3: One problem with this: while jQuery does support these attribute selectors, in my experience they require some pretty heavy lifting to do the pattern matching, which can slow things down significantly. Since the method above would require multiple selections (one for each extension/image combination), it makes sense to try a different way that will require fewer selections and less pattern matching:

 
var fileTypes = {
  doc: 'doc.gif',
  xls: 'xls.gif',
  pdf: 'pdf.gif'
};
 
// this is like $.each() above, except
// it iterates over the matched elements
$('a').each(function() {
 
  // get a jQuery object for each anchor found
  var $a = $(this);
 
  // get the href attribute
  var href = $a.attr('href');
 
  // get the extension from the href
  var hrefArray = href.split('.');
  var extension = hrefArray[hrefArray.length - 1];
 
  var image = fileTypes[extension];
 
  if (image) {
    $a.css({
      paddingLeft: '18px',
      background: 'transparent url("' + image + '") no-repeat center left'
    });
  }
 
});
 

And in fact, in limited testing using Firebug, this second version is faster than the first if you have more than two filetypes (and thus more than two selections).

Taking it further

You can also add a different icon to external links, and only add filetype icons to internal links:

 
var fileTypes = {
  doc: 'doc.gif',
  xls: 'xls.gif',
  pdf: 'pdf.gif'
};
 
$('a').each(function() {
 
  var $a = $(this);
  var href = $a.attr('href');
 
  if (
    (href.match(/^http/)) &&
    (! href.match(document.domain))
  ) {
 
    // use a special image for external links
    var image = 'external.gif';
 
  } else {
    // get the extension from the href
    var hrefArray = href.split('.');
    var extension = hrefArray[hrefArray.length - 1];
 
    var image = fileTypes[extension];
  }
 
  if (image) {
    $a.css({
      paddingLeft: '18px',
      background: 'transparent url("' + image + '") no-repeat center left'
    });
  }
 
});
 

Or, only add icons to certain links, like a list of files in an unordered list, by changing your selector from $('a') to $('ul#fileList a').

Resources

The class name method

In case you were wondering ...

First, put a class name on the link:

 
<a href="my-word-document.doc" class="word-doc">Word Document</a>
 

... and then style it using CSS:

 
a.word-doc {
   padding-left: 18px;
   background: transparent url('word.gif') no-repeat center left;
}
 

Related posts: front-end development

Related posts: howto

Related posts: jquery

5 Responses to “Unobtrusive, cross-browser method to add icons to links”

  1. Jamie says:
    January 6th, 2008 at 8:48 pm

    Elegant. I could see using your “taking it further” solution on E-Commerce sites that have videos and extended images for products. It would save a lot of time for merchandisers who play with the copy.

  2. James says:
    January 7th, 2008 at 6:39 am

    Hey, this is pretty cool. It’s a shame pure CSS stylesheets can’t give you the flexibility this approach does. Are there any real downsides to using javascript for link icons?

  3. rdmey says:
    January 7th, 2008 at 8:12 am

    @James: There are a couple of downsides that I can think of: the fact that users without Javascript can’t see it, the weight of the Javascript (while the code to accomplish this isn’t any longer than the CSS would be, the jQuery library is bigger, and also requires another HTTP request).

    That said, if you are already using jQuery on your page for something else (and more and more often, I am), that becomes less of a consideration. And there are a lot more people using IE6 than there are people without Javascript enabled, so I think the tradeoff there is fair.

  4. Automatic Link Icons v2.0 | Psyked says:
    January 8th, 2008 at 3:19 pm

    […] are other ways than just CSS, however. Check out this post by Rebecca Murphey, “Unobtrusive, cross-browser method to add icons to links” - using javascript to get the same […]

  5. Linklere Otomatik İkon | elektronik projeler devreler web grafik says:
    February 27th, 2008 at 1:27 pm

    […] hemen denedim bir türlü olmadı sonrasıda aynı sitede bulunan linklerden uygulamanın html ve farklı örneklerine ulaştım dene dene yok olmadı sonrasında ilk yapmam gerekeni yaptım ilk sitede […]

Comment