Seventh Octave

We're Starters. We write about culture, design and the business of software.

We believe software should be beautiful and inspired. Follow us as we build @TechOctave.

XHTML Strict Tweet Button and Facebook Like Button TVD Dec 13

9 comments Latest by TVD

We needed a smart way to grow targeted and relevant Twitter followers. The alternatives were either ugly, abandoned or downright shady (sometimes all three). There had to be a better way. There wasn't, so we built one! Checkout Tweetlr and build an audience like a Rockstar!

I like to chillax just as much as the other guy. But when it comes to cross browser compatibility, you know I'm all business. Well, I recently integrated with Twitter's Tweet Button and Facebook's Like Button for my open source project Blogcast. I was not happy with the results.

XHTML Strict 1.0 did not validate and after the upgrade to Rails 3, HTML5 didn't validate either! I needed a better way to integrate with Twitter and Facebook. I needed a way that didn't compromise validation and thus, maintainability.

Pure JavaScript Buttons for Twitter & Facebook

Inspired by the Digg Button, here's the XHTML Strict version of Twitter's Tweet Button and Facebook's Like Button:

Twitter's Tweet Button

Pure JavaScript Solution: Asynchronous.

Here, I use JavaScript to write the anchor hook for the Tweet Button to wrap itself around:

<script type="text/javascript">
//<![CDATA[
(function() {
    document.write('<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="YourTwitter">Tweet</a>');
    var s = document.createElement('SCRIPT'), s1 = document.getElementsByTagName('SCRIPT')[0];
    s.type = 'text/javascript';
    s.async = true;
    s.src = 'http://platform.twitter.com/widgets.js';
    s1.parentNode.insertBefore(s, s1);
})();
//]]>
</script>

Notice the Twitter JavaScript widget is written asynchronously. This way my page load isn't slowed by Twitter's widget since it is now non-blocking. Asynchronous means my blog content will load before any of the Twitter Tweet Button objects.

NOTE: Change the data-via attribute from "YourTwitter" to your actual twitter account. This will do two things:

  1. Through the via note, it gives you credit when your content is tweeted. E.g. XHTML Strict Tweet Button and Facebook Like Button http://t.co/URLsepW via @tiandavis
  2. Once your content is tweeted, Twitter suggests your reader to follow your twitter account. So this can be used as a method of increasing your Twitter followers.

Simply remove the data-via="YourTwitter" piece of code if you don't have a twitter account. Enjoy!

Query String Solution: Synchronous.

A synchronous solution is also available for Twitter's Tweet Button. Here, instead of using HTML5 data attributes, this solution passes the data attributes as query parameters to Twitter's share service:

<a href="http://twitter.com/share?count=vertical&amp;via=YourTwitter" class="twitter-share-button">Tweet</a>

<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>

This solution is somewhat cleaner and certainly involves less code. However, this solution also means Twitter's code will load at the same time as your app's code (synchronously). This could potentially block some of your content from loading until the Tweet Button has finished loading.

I'm not really a fan of this solution because I believe my content should Trump Twitter's Tweet Button and thus, I feel the Tweet Button should load after my content.

Also, for each property you should URL encode the value you are sending. Failure to do so could mean some of your URLs don't function properly. You won't have this issue if you choose the asynchronous Tweet Button solution.

For speed, reliability and maintainability, better to go with the asynchronous Tweet Button solution.

NOTE: Change the data-via attribute from "YourTwitter" to your actual twitter account. See above.

Facebook's Like Button

Pure JavaScript Solution: Asynchronous.

The same benefits achieved in the Tweet Button are achieved here with the Facebook Like Button:

<script type="text/javascript">
//<![CDATA[
(function() {
    document.write('<fb:like width="250"></fb:like>');
    var s = document.createElement('SCRIPT'), s1 = document.getElementsByTagName('SCRIPT')[0];
    s.type = 'text/javascript';
    s.async = true;
    s.src = 'http://connect.facebook.net/en_US/all.js#xfbml=1';
    s1.parentNode.insertBefore(s, s1);
})();
//]]>
</script>

In particular, I avoid placing the FBML tag directly in my XHTML code. It goes without saying that FBML is thoroughly not standards-compliant code. In addition, I see no reason to chase non-standard HTML headers just because Facebook thinks it's cool to have its own custom markup.

A Note on Maintainability

XHTML Strict concerns go beyond validation and truly speak to maintainability. The more XHTML Strict your code is, the less likely it is to break a piece of JavaScript.

Using semantic XHTML also increases the chance your application will display as expected across a wider variety of web browsers.

Also, when you do break validation, it will be easier to track the source without needless validation errors piling up from social media widgets. Inevitably, there will come a time when validation isn't achievable, but this isn't one of them.

Maintaining a clean XHTML Strict 1.0 code base may take a little more work, but I think it speaks to a higher calling than code. I think it speaks to Craftsmanship!

Until next time, take care Beloved!

If you enjoyed this post, subscribe for updates (it's free).

Email Address:

9 comments so far

Robert Ames 21 Dec 10

document.write is evil. Look into dynamic script node creation potentially tied into "onready".

TVD 21 Dec 10

@Robert There are some drawbacks with document.write, but evil seems a bit of a red herring. The biggest issue I can think of is trying to apply custom styling to the Twitter and Facebook buttons. For most people, they like the default styling and wouldn't think of changing it. For them, they just want a clean solution that will allow them to remain XHTML or HTML5 compliant. This solution does that with the added bonus of being non-blocking. That said, I am interested to see another solution enter the wild. Let me know if you ever put it together. I might try it out myself!

Davide Casiraghi 30 Dec 10

Great!!!!!!!!! this Like button is strict html!!!! fantastic, you are a great programmer!!!

edi 24 Feb 11

Hello I would like to ask how can I modify height property in your fb:like script. ty for answer

TVD 24 Feb 11

@edi The Asynchronous script is just a wrapper for Facebook's XFBML Like Button plugin code. Better to refer to Facebook on how to adjust the XFBML height: http://developers.facebook.com/docs/plugins/ If it's not possible to adjust the height, using XFBML may not be the best route for you - asynchronous or not.

Ryan Fitton 27 Feb 11

Thanks for the great advice, i'll be sure to bookmark this page and pass it on to others :) I've implemented your Facebook like code, it works and validated perfectly! Thankyou very much :)

TVD 27 Feb 11

@Ryan Glad to see you join the fold ;) I really liked your YOU image project. You have a lot of passion for our craft and it shows! I really like that this code validates XHTML Strict and HTML5. Still, I've got to say the non-blocking aspect is steadily becoming my favorite feature. As traffic increased, having my content load before Twitter and Facebook became even more a priority. Keep up the good work and stay in touch. Take care!

Michael Butler 04 Mar 11

I hate document.write also, but not sure if there is a way around it here. I don't think you can create node elements dynamically like . I didn't try it but I wonder if myElement.innerHTML = ""; would work Kind of annoyed that facebook chose to use custom XHTML elements instead of just a plain DIV.

TVD 04 Mar 11

@Michael I'm really not sure what custom XHTML elements buy Facebook over a plain DIV. Brand recognition comes to mind. But my best guess is Facebook wanted to leverage its existing API infrastructure. Still, the custom fb:like tags seem a bit involved for a "widget".

Comments are closed