Rails/jQuery magic: marking external links with a CSS class

Want to mark external links on your website with a little icon or a different colour? Well, you’ll want to give all those a tags a CSS class, and style them up accordingly. In this article I present an easy way to do this without directly altering all the links in your application, exactly as I implemented it on this popular celebrity charity news site.

jQuery, and its use in Rails apps

While us denizens of the Rails world have been using the Prototype javascript library for years, great alternative libraries have become popular. Among them, jQuery is the reigning king. jQuery is particularly good at selecting multiple parts of an HTML document and manipulating them en-masse, but Rails needs Prototype, both libraries weight in at over 120kb in total, and the two don’t live happily together anyway.

Thanks to Aaron Eisenberger’s nifty jRails plugin, though, we can evict Prototype from our Rails applications and use the shiny new jQuery toys instead.

Let’s define an external link as an a with an href attribute pointing to an ‘http’ URL that doesn’t start with the current site’s full base URL. Playing in Firebug’s console, we can try to find these elements using jQuery. First, the http links:

>>> $('a[href]').filter("[href^=http]").size()
111

Now, skip the links to the current site, which I’m running at “https://localhost:3000”:

>>> $('a[href]').filter("[href^=http]").not("[href^=https://localhost:3000]").size()
9

I (personally) don’t want to do anything to links containing images, and I can skip those as follows:

>>> $('a[href]').filter("[href^=http]").not("[href^=https://localhost:3000]").not(":has('img')").size()
2

Excellent! And it’s possible to specify all of that in one jQuery selector, which looks like this:

>>> $('a[href^=http]:not("[href^=https://localhost:3000]"):not(":has(\'img\')")').size()
2

So we can wrap this up in a function as follows:

function externalLinks() {
  return $('a[href^=http]:not("[href^=' + document.domain + ']"):not(":has(\'img\')")');
}

Now we’ve easily found the elements we want to modify, here’s where jQuery will put another smile on our face:

externalLinks().addClass("external");

To make this happen automatically from, say, a Rails app, we can put the “externalLinks” function in our application.js, and put the following in our master layout template:

A sprinkling of CSS

Let’s add a little “exit” icon after the text of each link:

a.external {
  background:transparent url(../images/external-link.png) no-repeat scroll right center;
  padding-right:17px;
}

More

Comments