I wanted to extend the concept of hyperlink cues a little. For links that point to external sites, what if, instead of showing a generic 'external link' icon, we showed that site's favicon?
Instead of this:

or this:

Do this:

The favicon gives the reader something to recognize if they are already familiar with the destination site, and if not familiar, something new to associate with it. It's similar to the way a feed reader, or a bookmark list, might show sites.
The method to do this requires some CSS, but the most of the magic happens with JavaScript.
Note: I'm no JavaScript guy, and I can say with great confidence that there are more efficient and fool-proof ways to accomplish some things I put forth. If you know how the JavaScript mentioned here can be improved, please let me (and everybody) know.
On with the show.
English before JavaScript
First I wrote out what I wanted to happen in English:
- Look for links on the page.
- If the link points to some other site, grab the favicon off that site.
- Place the favicon next to the link.
Considerations
- Favicons are easy to get. If a favicon exist, I can always count on it being in a predictable spot: it's always right off the root of a domain, like this: http://www.askthecssguy.com/favicon.ico. For this reason, there's no need to store favicons locally.
- Not all sites have a favicon. Though most of the sites I regularly visit have a favicon, not all do. In those instances, I could either show nothing, or have a generic image to indicate that a link is external.
- Not all favicons are the same size. Some are 16x16 pixels. Some are bigger. Yet I want all the favicons to have consistent dimensions. For this reason, I don't want to call the image as a CSS background image, since currently-supported CSS doesn't allow for resizing of background images. I'll have to call the image using the
imgtag, and style it with the dimensions I want.
Examples
View example pages and view source to see code.
- Faviconize Everything (View Page »)
The script will scan every link on the page and place favicons after any links that point off site, resulting in:
- The favilist (View Page »)
The script will only attach the favicons to links withinul class="favilist", resulting in:
- The favilist 2 (View Page »)
Same as above, but showing favicons at 'full-size' 16x16, so bigger text, too, resulting in:
- Faviconize Divs with Class (View Page »)
Only works on links within adivtag of a specified class. - Faviconize Divs and excluding a domain (View Page »)
I modified the 'faviconize all' script so that it will overlook a domain name of your chooseing. If you never want to faviconize pages that link to other pages on your own site, but your blog engine always puts absolute urls in your links, this might be helpful.
Room for Improvement
Here are some known problems. If you can help me solve them, please let me know!
- Safari doesn't support the javascript onerror event. If a favicon doesn't exist, it's the onerror event that tells the browser to use the standby "external link" image instead. For Safari, I just get a blank spot instead of my standby image.
- The regular expression I'm using to grab the domain name out of my link is far from the best one to use. I suck at regular expressions, and after hunting through tutorials with examples, I found one that worked, but it's got all this extra nonsense. It would be best to have one catered to my specific use. I just need to grab the domain from a link, like "www.wikipedia.org" from "http://en.wikipedia.org/wiki/Favicons".
- Resized images are not ideal anyway, but they really look like ass in Internet Explorer.
Updates
- December 30, 2006: Added example for only faviconizing
divtags with a specified class. - December 30, 2006: I decided to drink my own kool-aid and introduced this effect in my comments. If commenters left a URL, their name becomes a hyperlink to that URL, and the faviconize script should then show the favicon of that URL if one exists.
- December 31, 2006: I added another example. The new example shows how to modify the javascript so that you can specify a domain that will be ignored during the faviconization. (word?)
Comments (61)
Very very useful!
thanks!
Posted December 29, 2006 5:05 PM | #
I tried this but I didn't get any change. I have been manually styling external links with a generic image, but I couldn't get the favicons to work when trying this out. I just put the "Faviconize Everything" javascript in my header, then put the css in my external stylesheet, but got nothing. I assume it's the javascript that's not working for me, because the CSS doesn't add the favicon. It makes no sense that the javascript wouldn't work even though it was directly in the page header.
I still have the code on my site if anyone knows what's wrong. I shoved the javascript in my theme's head page.
Posted December 29, 2006 10:19 PM | #
Forgot to add that I still have the external link .gif styled as a background image, as well as the favicon code. Since it's a bg url, it shouldn't make a difference.
Posted December 29, 2006 10:23 PM | #
@liquid parallax -
Yeah - I see what you mean.
I saved one of your pages locally and attempted to see what was going on, but so far, I'm not sure. I'll keep at it.
With your locally saved page, I did a test and modified the javascript so that it only faviconized the links within any div with class=entrytext, which is what your blog entries are wrapped in, and that seemed to work. I added that option to the examples above.
I noticed that you have lots of links that point to your own site, and start out with 'http', so your own favicon shows up dozens of times. I may have to come up with a modification to prevent that sort of thing, since it's probably your content management system that is dynamically building those links.
I'll let you know if I find out anything about why faviconize everything isn't working for you. If you find out before I do, please let me know.
Posted December 30, 2006 9:42 AM | #
Hmm, I appreciate you looking at it. I've used the newer div class code and it half works. For instance, on this post, in Firefox it works until it gets to the Yamipod link. But in IE7, it faviconizes the whole entry.
Even stranger is that IE doesn't favicon Yamipod's site and keeps going, whereas Firefox stops altogether. It might be because Yamipod's favicon isn't in the root directory, but at http://www.yamipod.com/main/favicon.ico
Is it possible to search an external page's head tag for "favicon.ico" in javascript to avoid the above? It would probably take some extra Regex to scoop up everything from http:// -to- /favicon.ico
And I'll confirm that it also favicons my local pages. If I knew more JS or PHP I'd try to troubleshoot it more. Thanks again for trying to help.
Posted December 30, 2006 12:26 PM | #
Thought you could perhaps get around the Safari issue (and all non-existent-favicon issues) without any javascript at all by simply adding to your javascript the following:
1) Wrap each external-pointing link in a span tag.
2) Set the background image of the span to your generic icon (via a class on the <span>?)
3) Have the javascript set the bg image of the to the retrieved favicon.
If there's no favicon, the <span>'s icon shows through.
If there is a favicon that covers the span's icon.
I'm not a javascript jockey, but this shouldn't be so hard to do if you've already got the rest of the code working.
WDYT?
Nice site. Nice article. Thanks!
Posted December 30, 2006 9:39 PM | #
@liquid -
Weird that IE7 is the one that would actually work for everything and not Firefox. The error returned mentions "hrefvalue has no properties", but it's clear that it does. I'll have to continue looking into that.
I didn't realize that the new way of doing favicons is using the <link> tag, which would allow the favicon.ico to exist in places other than the root directory. Though from what I read on wikipedia, some browsers still only look for the favicon in the root no matter what the link tag says. Still, I'm not sure how to use javascript to scan another page's link tag to find that location.
@Anthony DeCrescenzo:
I like the suggestion of having a default icon, and having the favicon, if there is one, cover up the old one. I'll try to think of a way to do this without background images - I don't want to use the favicon as a CSS background image because background images can't be resized, and favicons exist is more than one dimension.
Posted December 30, 2006 11:35 PM | #
@liquid -
See the latest example (5th one) to view how to exclude your own domain from the faviconization process. Tested in FF2 for mac.
Posted December 31, 2006 10:49 PM | #
I really like this script, and i also think that it's cool that you have an elephant on all of ur own comment posts.
You truly ARE a CSS Guy!!!
Regards!
Posted January 2, 2007 6:52 AM | #
Amazing, you are a born genius!
Posted January 5, 2007 5:33 PM | #
Hmmm - I'm not convinced of the utility of this technique personally. I instantly recognised the intent of your second example, using the 'arrow-in-a-box' icon, but felt slightly confused by the second example using favicons. Why? Because I'm not familiar with the second site in your example, and didn't recognise either of their favicons. I think it's too great an assumption to assume that *any* of your readers will be familiar with the target site, let alone a majority. The 'arrow-in-a-box' icon, and its variations, represent something of a de facto visual standard for representing external links, and messing with that failed a basic usability test for me.
Having said that, I can see it working for very well-known sites, like Amazon, Wikipedia, Google etc. I think your own examples tell the story - the second-last listing has 3 links I instantly recognise, and the others have me scratching my head, trying to glean something from the link text itself (and I'm familiar with kottke.org, but again, not its favicon).
Posted January 5, 2007 8:30 PM | #
As much as I like this, I'm still a bit frustrated about it working smoothly, especially in Firefox. Your newer code (5) is exactly what I was looking for, then I added a second function to style comments too and all seems to be working correctly...
until I found a bug. In FF2 on XP, it stops at an "keep reading the rest" anchor link with no href, and only an id (and no text between the "a" tag). Inside brackets is a id="more-###". It styles any links before this and stalls on any other link afterfwards.
I can't recode the anchor because wordpress handles it, but I'd still love to be able to use this. If you have any explanations, I would be very grateful. This is the only bug holding me back. I'm guessing it fails as soon as an "a" tag doesn't have an href tag, but I still can't seem to fix it.
Sorry to bother you so much.
Posted January 6, 2007 5:58 PM | #
A really interesting idea! I'm still playing with it, as on some pages it becomes visually overwhelming with many favicons, but I'll definitely implement it on my site.
A suggestion I would have is not to insert the image after the link, but inside the link with appendChild. Any :hover styles on the link would then also apply to the image. It works especially well for me, as I give the downloaded favicons an opacity by default, and when one hovers the link, they become fully visible.
Thanks again for this idea!
Posted January 6, 2007 11:44 PM | #
@liquidparallax.
If you want the script to skip anchor links like that, you can change the following line:
if (hrefvalue.search(hoststring) != -1) {
into
if (hrefvalue && hrefvalue.search(hoststring) != -1) {
This way the code only executes if the hrefvalue exists, and it should therefore skip links the one you describe.
Posted January 7, 2007 11:18 AM | #
It's Beautiful!!!
Posted January 8, 2007 6:50 PM | #
Really a nice idea!
Will use it for sure.
Posted January 9, 2007 2:25 AM | #
@Mark:
That fixed everything. Now I am completely satisfied. Thanks to CSS Guy too!
Posted January 10, 2007 3:17 AM | #
Great! I will try to adapt this as soon as possible! :-)
Posted January 11, 2007 2:54 AM | #
Good job
Posted January 11, 2007 3:19 AM | #
Great thinking, really nice trick
Posted January 16, 2007 1:33 PM | #
This would be interesting as a greasemonkey script. :-)
Posted January 27, 2007 1:36 PM | #
When hovering over, try this nice hand icon instead of the standard I of edit :)
function highlightRows() {
if(!document.getElementsByTagName) return false;
var tbodies = document.getElementsByTagName("tbody");
for (var j=0; j var rows = tbodies[j].getElementsByTagName("tr");
for (var i=0; i rows[i].oldClassName = rows[i].className
rows[i].onmouseover = function() {
this.style.cursor='hand'
if( this.className.indexOf("selected") == -1)
addClass(this,"highlight");
}
rows[i].onmouseout = function() {
if( this.className.indexOf("selected") == -1)
this.className = this.oldClassName
}
}
}
}
Posted February 2, 2007 7:43 PM | #
Sorry about the dupe, I gave the wrong address! The wife was grabing my ear @ the same time...
You know the blah,blah,blah. :)
When hovering over, try this nice hand icon instead of the standard I of edit :)
function highlightRows() {
if(!document.getElementsByTagName) return false;
var tbodies = document.getElementsByTagName("tbody");
for (var j=0; j var rows = tbodies[j].getElementsByTagName("tr");
for (var i=0; i rows[i].oldClassName = rows[i].className
rows[i].onmouseover = function() {
this.style.cursor='hand'
if( this.className.indexOf("selected") == -1)
addClass(this,"highlight");
}
rows[i].onmouseout = function() {
if( this.className.indexOf("selected") == -1)
this.className = this.oldClassName
}
}
}
}
Posted February 2, 2007 7:47 PM | #
Hello, your script works on firefox when I see it and copy it into an html page. But when I added it to my phpBB forum, I could only see it in IE7. Whats wrong? How can I make it viewable in firefox and other browsers again?
Posted February 2, 2007 7:51 PM | #
Also, I am using the first example, faviconize everything.
Posted February 2, 2007 7:53 PM | #
@Kevin:
Do you have a URL of the forum with the script in place?
Posted February 3, 2007 2:36 PM | #
Sorry I dont, I am currently using it in my localhost
Posted February 3, 2007 2:56 PM | #
You probably wont, or atleast not for me, but if you do download it and install it, I put the script in templates/subSilver/overall_header.tpl
In there, I put the script right before the </head> tag
Posted February 3, 2007 4:29 PM | #
Great tutor! and useful tips.
Posted February 4, 2007 10:56 PM | #
Quite nice,
I might try to incorporate an alternative implementation of this on my site using PHP/CSS instead of CSS/Javacript.
Might even parse the remote link so I'll be able to handle a <link rel="shortcut icon" href="http://HOST.TLD/images/favicon.ico" />
Thanks for the great idea
Posted February 11, 2007 7:17 PM | #
Great idea. Nice site to !
Thks :-)
Posted February 12, 2007 5:11 PM | #
this is amazing and that useful!
Posted February 18, 2007 8:17 PM | #
Hey, you've created a pretty useful thing here.
Congrat's.
I'm using this on my website too.
I've edited your thing to let me grab favicon's from websites only for selected div's and exclude my domain.
It works OK, well.. At least for the front page.
I don't know what the problem is but it doesn't work at inner pages, single posts. Can you have a look at my website and tell me the problem if you can figure it out?
http://az.cokh.net
Posted March 2, 2007 6:30 AM | #
@M.:
I think what is occurring is that the script is getting hung on anchor links for those other pages. I should incorporate into my sample scripts what Mark stated in one of the above comments, and make sure we test all links for an href before proceeding.
In your code, change:
if ((hrefvalue.search(hoststring) != -1) && (hrefvalue.indexOf(localdomain) == -1)) {
to
if (hrefvalue && (hrefvalue.search(hoststring) != -1) && (hrefvalue.indexOf(localdomain) == -1)) {
See if that doesn't do the trick.
Posted March 2, 2007 11:04 AM | #
Well, i've changed the code as you've mentioned.
But still, it works only at the frontpage.
I don't know why. It's working with div's and i've set it to show favicons only in "content" div which both the frontpage and inner page's have.
Posted March 4, 2007 3:47 AM | #
Bit of caution, this
cue.onerror = function () {
this.src = "external.gif";
}
will cause an infinite loop if external.gif also errors for some reason.
Also you are setting localdomain = in every iteration of your for loop. I would declare it before the loop.
This is really very nice, I plan on making it based on <a> classname, if i make any tweaks to the reg ill be sure to let you know. Thanks for a great starting point.
Posted March 16, 2007 11:29 AM | #
Well, in the end, i've removed the code. No matter how much i struggle, it didn't work at the inner pages!
Sadly, i had to say bye to your script.
(:
Posted March 23, 2007 2:41 PM | #
I really like this solution b/c it's a lot easier than creating lots of classes for every a href. I did this for my youtube, myspace, amazon, etc. links, because I want people to see immediately where the link will take them (and I hate the snapr thing).
But it's a big pain in the a** to include the class attribute to nearly every link you're putting up, takes up way too much time.
However, your solution would be even better with a little tweaking I think. For example, I'd love to combine the Faviconize Divs with Class and Faviconize Divs and excluding a domain solution. In my blog, I'd only like to have the links in the .post-content div styled, and I'd like to exclude my own domain. Is this possible?
Furthermore, I'd like to exclude images inside the .post-content div from the javascript as images linked to amazon or flickr e.g. are also getting the additional favicon, and that messes up the design. Do you think this would be possible?
The third thing I'd like to mention is that maybe it would be cooler if the javascript would not place img tags, but css background-url tags, in order to give the links some favicons. (The solution you mentioned in your previous favicon tutorial). That gives the user a lot more room to customize the images and their position in the text. But as I'm a total Javascript Noob, I don't know if that's possible.
greetings,
aloha
Posted May 29, 2007 1:47 PM | #
@Aloha:
I'm pretty sure your first two points would be doable by tweaking one of the javascript examples. I realize you mentioned that you are a total noob, but I'm probably not going to be able to do any customizations anytime this week. Instead, please purchase or borrow or check out at the library Dom Scripting by Jeremy Keith. (You'll need to know that stuff eventually anyway.) I don't say that so you'll go away, but as a sincere suggestion and encouragement. This is the kind of stuff that we (web designers) need to know how to do!
As to your third point, the reason I made this <img> tags rather than css background images is so I could control their dimensions. Some folks make favicons that aren't just 16x16 pixels, and even for those that are 16x16 pixels, sometimes you just want to show them at a 10x10 size, or 12x12, or even a 100x100. You can't do that with a CSS background image. Hope that is helpful info.
Posted May 29, 2007 3:16 PM | #
I am trying to implement the document type icon after links to docs on my site using your method. However, unlike your examples, the icon becomes part of my link (the link underline extends to the icon too). How does yours NOT do that?
Posted September 5, 2007 4:24 PM | #
@Angela:
Do you have a url where I can take a look?
Posted September 5, 2007 5:21 PM | #
i am new to this css. I have been searching online for a way to add a favicon to every page on my site without having to manually add it to each pages header tag. i seem something like adding
.pagehedear to a css stylesheet.
what would you recommend any comments are welcome
Posted January 1, 2008 10:48 AM | #
@ sixxkilur:
Start here: http://msdn2.microsoft.com/en-us/library/ms537656.aspx
Posted January 1, 2008 11:54 AM | #
I thought that favicons were always 16x16 pixels - is that not the official standard?
Posted February 20, 2008 8:04 AM | #
I thought that favicons were always 16x16 pixels - is that not the official standard?
Posted February 20, 2008 8:05 AM | #
Very nice and I am going to try to implement it in my site! :-)
Posted February 21, 2008 2:39 PM | #
Mike:
As Wikipedia (http://en.wikipedia.org/wiki/Favicon):
* ICO: include multiple resolutions (the most commonly used being 16×16 and 32×32, with 64×64 and 128×128 sometimes used by Mac OS X) and bit-depths (most common being 4, 8, 24 bpp—i.e. 16, 256 and 16 million colors) in the file.
* GIF: use 16×16 in 256 colors.
* PNG: use 16×16 in either 256 colors or 24-bit.
Posted February 21, 2008 6:05 PM | #
Instead of relying on onError, create your IMG tag as a DomElement, using your 'default' placeholder image. Then go away and fetch the favIcon, and if you don't find one, your image still contains the default image, otherwise swap out the SRC attribute in your new dom element. THEN add it to the document.
I've not looked at your source, so I've assumed you're using nice, proper DOM scripting and not InnerHTML but the above should apply there too.
I'm no javascript expert either, but that's how I'd get around the safari issue.
Posted February 22, 2008 2:22 AM | #
that might be something for snap (snap.com - integrating snapshots of external sites into your links). sounds useful!
Posted February 22, 2008 2:47 AM | #
Nice script, I think I'll use it for our news page!
FYI this is what the parts of the regex mean (roughly - I studied them about 7 years ago...)
Entire regex: (\w+):\/\/([^/:]+)(:\d*)?([^# ]*)
(You can ignore the / at the front and back in the code - these are the Javascript regex equivalent of "quotation marks" for string values)
Catch the protocol with (\w+):\/\/
\w means a letter
\/ means just a forward slash /
+ means 1 or more.
The brackets denote a numbered group you can pull out later (starting at 1).
Catch the domain with ([^/:]+)
Square brackets specify a group of characters which might match.
^ means NOT the characters inside the brackets.
+ means 1 or more repeats.
So [^/:]+ means match all characters until / or : is encountered.
The round brackets make this a numbered group you can retrieve later (number 2).
Everything after this can be left out I think (I haven't tried it yet though): it just identifies all the other parts of a full URL, which we don't need here.
Port: (:\d*)?
URI: ([^# ]*)
I think sticking something like this on the end would catch the local anchor, but I could be wrong:
(#([\w]*))?
Posted February 22, 2008 3:27 AM | #
Now this would be a cool jquery plugin
Posted February 22, 2008 8:39 AM | #
Hey Now,
I really like the concept of the favicon displayed.
Thx 4 the info,
Catto
Posted February 22, 2008 1:52 PM | #
Instead of switching images on error, couldn't you first use the default image and then onload of the external favicon-image you switch to that.
If there's no image, the onload will never fire and the default image will not change.
// Insert default image next to link
var favImg = document.creageElement('img');
favImg.src = 'default.png';
favImg.insertBefore(link);
// Load favicon
var extImg = new Image();
extImg.src = faviconSrc;
// Replace default image onload
extImg.onload = function() {
favImg.src = extImg.src;
};
Also, it's not entirely trud that the favicon.ico is _always_ in root. As far as I know it is valid to place it anywhere and reference it from a link-element in the head-element.
I've created a similar script that takes a site-URL and returns its favicon-URL, be it in root, some place else or non-existent.
Cool trick, great article.
Posted February 25, 2008 7:25 AM | #
I was googling around for some tips on using favicons and came across this article.
I'm thinking about using this technique, but I'm concerned about how it might turn off some users.
The reason I'm concerned is that on some (often lower-quality) sites, there are in-text ads that mess around with external links (some of them add a little image, some of them throw weird hover things, some of them add a double-underline on random words, etc).
I'm worried that a user might quickly scan the content, see the favicons, and think it's some sort of advertisement spam thing instead of something useful.
Posted February 25, 2008 8:09 PM | #
i think this a great idea. However people may say, the script is not good. Then i think they should do better. Maybe we can say "this script is not useful or i did not like it.
i will check out your other works and i will publish them in my own blog. Of course i will write down the origanal article links. Hope there is no problem with that..
thanks agan, again....
Posted March 2, 2008 3:51 PM | #
@Andreas:
I like that idea of using the external link by default, and replacing it with the favicon if one exists.
Posted March 2, 2008 6:25 PM | #
Cool, that's how I did it and t seems to work fine cross-browser.
Posted March 3, 2008 6:56 AM | #
Nice. I hardcode the favicons paths into my bookmarks. This is much neater. The only change I made was putting the favicons before the URLs. Also need to update it for dynamically created a-tag lists like in my bookmarks.
Thanks!
Posted April 16, 2008 9:19 AM | #
CSS Guy,
First, let me say that this is a great addition to most blogging sites, like mine.
For me, it worked, but with a few problems. My site is setup as a tumblelog powered by WordPress. In the theme, categories determine the formatting of the posts.
When I add the javascript code, I am telling it to pull the WP div tag, "entry-content". This works as it doesn't look at my navigation links and pagination any longer.
However, I would like to tell the script to only look at external links so that photos and other internally linked things in my tumblelog dont' have my favicon attached to them.
Do you have any advice on how I can troubleshoot this problem?
Thanks in advance,
CP
Posted April 29, 2008 8:13 AM | #
@CP
Does this example cover what you're asking? excludelocal.html?
Posted April 29, 2008 10:30 AM | #
I hacked the DivClass version with the example you linked to and it appears to work. Thank you!
Posted April 29, 2008 10:42 AM | #