Let’s face it the clever guys at Google have more bandwidth than the rest of the nation combined. What better to do with all that excess pipe ;) There are of course numerous posts about the performances of +1 buttons. If you missed them there is the ever popular Google +1 Button Performance Review, and Why You Should Not Implement the Google +1 Button At This Time. Both of these have since been updated to indicate that the issues have been addressed. While I will admit that they have solved making the buttons asynchronous (If you implement it correctly) they are still far from done IMHO.
As you may or may not be aware I’ve recently added plus-one buttons to all the post titles on my site in the hopes that you will click one for me. Go click one. I mean it. Never-mind. Anyway the +1 button is cool but it currently performs like a dog. For every button you display an iframe is created that internally uses 5 different resources. Then of course there are two scripts on containing page. The worst part for me is waiting to see these ‘magic’ buttons just pop up out of the blue a second or so after the page loads. All-in-all it is not an impressive experience, so I decided to do something about it.
Completely Lazy Loaded +1 Buttons
It turns out it is really easy to get the experience I wanted. I wanted the +1 button images to show up immediately and then if someone desires to interact with them we’ll create the ‘real’ +1 button. The following solution was created to do just that, inline images and no scripts until required.
The first thing we need is a new HTML placeholder to use instead of the “g:plusone” tag. I chose to use an anchor tag, but a div works too:
<a class="plusone" title="+1" onclick="return false;" href="http://csharptest.net/index.html" onmouseover="renderPlusOne({parent:this,href:this.href});" > </a>
If you are using a div tag you can remove the onclick handler, but this gets us… what? a link? … no we some css to turn this anchor into a proper placeholder:
.plusone { display: inline-block; width: 24px; height: 15px; padding: 0px; margin: 0px; overflow: hidden; border: none; background-image: url("http://csharptest.net/images/plusone.png"); }
The image I’m using ‘plusone.png’ was extracted from +1′s sprite.png for the size I wanted, small. So at this point we have a nice place-holder that only needs the single image resource to render. Now what do we do with the scripts? Well we need to implement the ‘renderPlusOne’ method from the ‘onmouseover’ event above. Google was nice enough to provide a gapi.plusone.render method that allows us to explicitly render the +1 button. The only problem is before we call that method we need the plusone.js script on our page. So we have two choices, load it even though we may not use it, or defer loading it until the user wants it. Obviously I’m going after the later approach. If you don’t mind the script, just load it and you’ll only need to call render directly in the onmouseover event. Assuming you want to lazy load all scripts you just need to include the following javascript fragment:
var loadgapi=(function(item){ loadgapi=null; var po=document.createElement('script');po.type='text/javascript';po.async=true; po.src = 'https://apis.google.com/js/plusone.js'; po.onload = (function() { renderPlusOne(item); }); po.onreadystatechange = (function() { renderPlusOne(item); }); var s=document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); }); function renderPlusOne(item) { if(loadgapi != null) { loadgapi(item); } else { try { gapi.plusone.render(item.parent, { href: item.href, size: "small", annotation: "none" }); item.parent.onmouseover = null; } catch (e) { } } }
I’ve run this in the only browser that matters, Chrome, as well as a few of the others like Safari, Firefox, and IE (8 and 9). Try it for yourself, all the plus one buttons on this page are using this code. Feel free to drop a comment by following the title link.
Sample: