Unless we make a custom CSS selector for every single site we want to do this for, CSS isn’t capable of yanking the href
off links and using it to plant a favicon next to the link. But if we involved a smidge of JavaScript, we can get it done.
The “I Wish” CSS Only Technique
What would be nice is if you had simple semantic HTML like this:
<a href="https://github.com">GitHub</a>
And then you could access everything you needed to insert a background image of the favicon using a service like getFavicon.
/* Fair warning, this doesn't work */
a[href^="http://"]::before {
content: url(https://g.etfv.co/ + attr(href));
}
Maybe the syntax wouldn’t be exactly like that, but something like it. The point is, you can’t mix up the url() syntax into parts like that in CSS.
Google’s Favicon Service
Google has it’s own favicon service you can use. For example:
https://www.google.com/s2/u/0/favicons?domain=css-tricks.com
Automating
The trick is you need just the hostname and TLD and nothing else. I searched around and found a simple regex for getting that from any URL. We’ll need that because links aren’t always (or even usually) the root of sites.
function getDomain(url) {
return url.match(/:\/\/(.[^/]+)/)[1];
}
Using these things, and jQuery, we’ll find all links and apply the favicon as a background image. The external link checking is pretty rudimentary, but there are more robust methods here if need be.
$("a[href^='http']").each(function() {
$(this).css({
background: "url(http://www.google.com/s2/favicons?domain=" + getDomain(this.href) + ") left center no-repeat",
"padding-left": "20px"
});
});
Then @travis reminded me that you can just use this.hostname
instead of the fancy regex. So:
/* Nothing else needed */
$("a[href^='http']").each(function() {
$(this).css({
background: "url(https://www.google.com/s2/favicons?domain=" + this.hostname + ") left center no-repeat",
"padding-left": "20px"
});
});
I’m not sure what the browser support is for hostname
, whether it’s just as good as href
or less so, not sure.
getFavicon Method
@seanodotcom showed me another similar service galled getFavicon.
It’s hosted by Google AppEngine, but it’s not Google’s own service. I did find it a bit slower. But the advantage being that you don’t need to deal with host names at all, you just give them the full URL.
So then it becomes:
$("a[href^='http']").each(function() {
$(this).css({
background: "url(https://g.etfv.co/" + this.href + ") left center no-repeat",
"padding-left": "20px"
});
});
Performance?
As I’m sure you know, the number of HTTP requests a page makes is a huge deal in performance. Each little image in these techniques are one page request each.
@yuritkanchenko pointed out to me a cool favicon service that can automatically sprite the favicons for you so you can keep it to one request.
For instance:
http://favicon.yandex.net/favicon/google.com/yandex.ru/css-tricks.com
I’m afraid I didn’t go the extra mile here and write the JavaScript needed to find all links, concatenate the domains, make the request, and then apply the images as a sprite, but I’m sure you could whip that up pretty quick if you really needed it.
The CSS Values and Units Module Level 3 specifications describeds that this should work:
(source)
Huh. Didn’t even know that favicon services even existed. I could imagine this being put into use, especially with favicons becoming the “identity” of a website, more or less.
+1 for the “I Wish” CSS Only Technique. I wish this was true…
I actually tried a similar approach these days and I also ended up using a jQuery solution.
I was discussing exactly this with Lea Verou back in April, too bad no browser implements Level 3 attributes yet
http://twitter.theinfo.org/192968593087004675
Because you’re loading the favicons with JS, the extra HTTP hits shouldn’t be that big of deal, right? It all happens after page load.
@Aaron: It happens after document.ready, but images and whatnot will still be loading, and it would be nice if they all popped in at once!
haha, pretty fun. Spent about 5 minutes mocking something stupid up.
http://jsfiddle.net/95A4h/
I quite like this solution, although one tip would be to adjust the selector (at the top of the JS) so that it only selects HREFs that are to domains other than the domain we are on, or to only select HREFs that have a corresponding target=”_blank”…
There’s no point in favicon’ing internal links in our own site! :)
theres a few other things that should be added if you actually wanted to use this in production.
– remove duplicate domains from array
– sort them then generate the background url
this way it wouldn’t have to load multiple favicons for the same domain, and it would be able to cache the generated sprite :)
here You go:
http://jsfiddle.net/95A4h/20/
changes:
1. favicons for links, so there’s no need to pass initial selector to links
2. added container selector, in case You want to apply it only to one container
3. used $.map in favor of $.each
you’ll also need to break it up into separate requests for a large number of links, too many will give you a 414 Request-URI Too Large
true, but only if the list of unique domains/pages ( different pages could have different favicons )
played around a little and it hit me – why do we have to inline-style every single link with the same repeating css rule? why not create some kind of small style manager that would create a class, inject it and return class name that could be applied – way cleaner, feels better
and that’s how stylist.js was born – independent ( u can use it with every framework You like ) – 2 days work so far, already works, now working on parsing input shorthand css rules passed as string – will post results when i’m more or less done :-)
A solution might be to use Favatar that not only retrieves various images for the web page (apple-touch-icon, og:image etc…) but also returns them as a `data:` elements, possibly making them easier to insert via CSS.
Hello.
Chad Scira has already done, but, here is another approximation : ) (I use to show the favicon, in that way you can change the font size)
http://jsfiddle.net/tx2z/WTAr9/225/
Saludos!
I’ve used “span” to show the favicon*
im having problems with this.
ive copy and pasted the javascript into the
is that all I need to do??? because it does not work for me
im using wordpress if that makes any difference?
as you can probably tell im an amateur so dont be to hard on me!
τακακια – Have you included jquery?
hi the only thing I did was put the javascript from your post in the head. im missing something right?
Yep, you have to include also jquery to make it work.
Un saludo
ok, where can I find? :-(
Greetings,
I do not know if I get something wrong now, but what’s with simply abusing the title attribute and targetting this in css ?
Really… can someone describe me what’s the problem here?
I Mean simply put your favicons on your server, why need an external service for that?
Dude… seriously? It means I save 30 seconds… That’s like saying: Why go to Burger King and spend $5.00 when you could cook the same thing(but healthier) at your house in about the same time for $1.00… every muscle I move brings me one muscle move closer to death… So basically… I don’t wanna die, that’s why this is a great idea…. Your thought process is allll outa-wack man… seriously…
Aww sweet man I just saw your name, it’s like a ninja name, I bet you yell your own name when you fly across the room with your ninja sword, all “UTZZZUTTZZZZ!!!!” *chop*… Kill Bill style with the garden hose fountain of blood flowin’… I didn’t really get that movie though, I just wasn’t IN-to it, ya know? Maybe i’ll watch it again and see if it hits more to home now that i’m older and am married..
awesome, dud… made my day ;)
..and your not even far of reality. You better talk about yourself in third person, when being ninja master and son of Tonny fuckin Montana.
The problem is load time and requests. If one were to use this with a page with many external links (Classified Ad page, for example), then they may considering using a caching technique such as using PHP to download the images once a day.
Good call SodaPop… Load time is everything and every millisecond matters.
Greatfull discussion……….and also nice article……….I m follow this site………
Re support for
HTMLAnchorElement#hostname
: It’s not listed in DOM2 HTML, but I tried it and found it broadly supported on desktop browsers: I tested all of these successfully:Recent Chrome (I don’t have older copies)
Firefox 3.6 (and so presumably all since)
IE6 (yes, really, and so presumably all since)
Opera 11
Konqueror 4.7.4
Safari 5.1
Midori 0.4.0
Didn’t try mobile browsers.
I really like the JSFiddle tool. Have used sqlfiddle before. Thanks for letting know the services to retrieve favicon.
Great article Chris! I will defiantly be using this in my next project!
It would be nice to be able to get the title attribute as well in cases where you have lots of links and dont want to manually add a title for each link.
Anyone know if this is possible?
Just wish it didn’t need jq… but very user friendly thing to do :)
OpenDNS just informed me the “demo” site is a phising web site.
Glad I didn’t got tricked through this web site to go there and get personal data mis-purposed.
I did something like that, as a jQuery plugin, previously. It works with most sites since most of them already have /favicon.ico in their main directory. And performance is better, since you’re sending only one image request.
Usage is pretty simple too, just add two lines from included gist and then add ‘fav’ class to any <a href="" /> in your code. DONE.
http://goo.gl/Ft1dM
I hope someone ‘ll enjoy it :)
PS. If you find some errors feel free to comment on code on gist. Cheers!
Cool, sir. I’ll try
@Maurice: Does the jQuery go into the site head within the tags?
@Avinash: There’s plenty of possibilities. The one I use the most is keeping one file for your scripts and another just for plugins, and in that case just add first line to this file and second one where you find it suitable for rendering/downloading favicons to start.
If you don’t want to use plugins.js file then you can put it anywhere you like: in <head> in script tags, or somewhere in your main scripts file. Just remember to run this plugin (2nd line) AFTER jQuery is loaded :)
PS. hack if you’d like to use this script from my gist – add this to your head after jQuery. Example:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"><script>
<script src="//gist.github.com/2003935/50f1d70f8e936a4eaf9ea8608aba2022c3e2b972"><script>
BTW, Coda 2 just came out…
a[href*=”css-tricks.com”] {
padding-left: 18px;
background: url(http://www.google.com/s2/u/0/favicons?domain=css-tricks.com) left center no-repeat;
}
<a href="https://css-tricks.com/">CSS Tricks</a>
I think this is because it seems to load the favicons directly while googles service seems to use a cache… My own website is currently down :( and I testet it with getFavicon and it took ages to load and then showed a placeholder. When I tried it with Googles service it didn’t take long time to load but also showed a placeholder. I think this is because Google caches the icons and I currently have searchbots forbidden in my robots.txt …
Thanks, I didn’t know that favicon services existed. This is useful to know! Might use it in the future.
I did not know that such a thing exists.
I wonder if I ever need it.
I did a little update (made them require a class) so that you can just copy and paste :)
http://jsfiddle.net/WTAr9/664/
Thanks for this excellent Tip :) i just hope sites don’t go adding / changing to dirty icons after posting a link to them lol.
Regards, Darren
That’s so nice!
I like the idea! Not a bad outcome either, nice work! :)
And by the way, seems like we’re forced to use “http://” in the website field in the comments – good usability would allow me to type my adress in without using “http://”. :)
I must say, this is a pretty spiff CSS application.. Definitely will be using this very soon. Kubashi.
I’d like to thank you for the efforts you’ve put in penning this site. I really hope to see the same high-grade content by you in the future as well. In truth, your creative writing abilities has motivated me to get my own, personal website now ;)
Good discussion. The script load time in milliseconds is the big thing.
Hello, any body know how to set the size for favicon?
Thank you.
I got it.
$(“a[href^=’http’]”).each(function() {
$(this).css({
background: “url(http://g.etfv.co/” + this.href + “) left center no-repeat”,
“-webkit-background-size”: “16px”,
“-moz-background-size”: “20px”,
“-o-background-size”: “16px”,
“background-size”: “20px”,
“padding-left”: “20px”,
“margin-left”: “10px”
});
});