A jQuery Twitter Ticker
Created by Martin Angelov on Oct 10th, 2009
Introduction
In this tutorial we are going to create a pure jQuery & CSS twitter ticker which utilizes Twitter’s Search API. It will show your or your friends’ latest tweets, and will not require any server side code or databases. As a result, the ticker will be easily included into any web page and easily modified to your likings.
Step 1 – XHTML
The XHTML part is quite straightforward.
demo.html
<div id="twitter-ticker"> <!-- Twitter container, hidden by CSS and shown if JS is present --> <div id="top-bar"> <!-- This contains the title and icon --> <div id="twitIcon"><img src="img/twitter_64.png" width="64" height="64" alt="Twitter icon" /></div> <!-- The twitter icon --> <h2 class="tut">My tweets</h2> <!-- Title --> </div> <div id="tweet-container"><img id="loading" src="img/loading.gif" width="16" height="11" alt="Loading.." /></div> <!-- The loading gif animation - hidden once the tweets are loaded --> <div id="scroll"></div> <!-- Container for the tweets --> </div>
The twitter ticker operates only if JavaScript is present and enabled. That is why we are hiding it in the CSS and showing it with jQuery. This will insure that it is only shown if working properly.
In the design I used an amazing twitter icon by freakyframes.
Lets move to the CSS

A jQuery Twitter Ticker
Step 2 – CSS
This is the place you should start from if you plan to modify the demo.
demo.css
body,h1,h2,h3,p,quote,small,form,input,ul,li,ol,label{
/* Resetting some of the page elements */
margin:0px;
padding:0px;
}
h2.tut{
/* This is the "MY TWEETS" title */
color:white;
font-family:"Myriad Pro", Arial, Helvetica, sans-serif;
font-size:16px;
padding:12px 0 0 58px;
text-transform:uppercase;
/* The CSS3 text-shadow property */
text-shadow:2px 1px 6px #333;
}
#twitter-ticker{
/* Styling the ticker */
width:200px;
height:300px;
background:url(img/slickbg.png) no-repeat #f5f5f5;
color:#666666;
display:none;
/* Rounded corners */
-moz-border-radius:10px 10px 6px 6px;
-khtml-border-radius: 6px;
-webkit-border-radius: 6px;
border-radius:6px;
text-align:left;
}
#tweet-container{
/* This is where the tweets are inserted */
height:230px;
width:auto;
overflow:hidden;
}
#twitIcon{
/* Positioning the icon holder absolutely and moving it to the upper-left */
position:absolute;
top:-25px;
left:-10px;
width:64px;
height:64px;
}
#top-bar{
height:45px;
background:url(img/top_bar.png) repeat-x;
border-bottom:1px solid white;
position:relative;
margin-bottom:8px;
/* Rounding the top part of the ticker, works only in Firefox unfortunately */
-moz-border-radius:6px 6px 0 0;
}
.tweet{
/* Affects the tweets */
padding:5px;
margin:0 8px 8px;
border:1px solid #F0F0F0;
background:url(img/transparent.png);
width:auto;
overflow:hidden;
}
.tweet .avatar,
.tweet .user,
.tweet .time{
float:left;
}
.tweet .time{
text-transform:uppercase;
font-size:10px;
color:#AAAAAA;
white-space:nowrap;
}
.tweet .avatar img{
width:36px;
height:36px;
border:2px solid #eeeeee;
margin:0 5px 5px 0;
}
.tweet .txt{
/* Using the text container to clear the floats */
clear:both;
}
.tweet .user{
font-weight:bold;
}
a, a:visited {
/* Styling the links */
color:#00BBFF;
text-decoration:none;
outline:none;
}
a:hover{
text-decoration:underline;
}
#loading{
/* The loading gif animation */
margin:100px 95px;
}
And as any experienced front-end developer can assure you, the code is not complete without some special IE6 treatment.
<!--[if lt IE 7]>
<style type="text/css">
div.tweet {
background:none;
border:none;
}
div#twitIcon{
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=img/twitter_64.png, sizingMethod=crop);
}
div#twitIcon img{
display:none;
}
</style>
<![endif]-->
This will take care of the PNG transparency issues in IE6.
Below you can see a detailed explanation of the twitter ticker.

The Twitter Ticker Explained
Now lets take a look at the jQuery source.
Step 3 – jQuery
Being front-end only, the widget takes advantage of the Twitter’s Search API. This a really simple solution for fetching data from the twitter’s infrastructure without the need of any server-side code or databases.
Here is how it works:
- The ticker loads;
- JS builds the twitter search api URL from the provided twitter usernames (in the tweetUsers array) and a name of a callback function (TweetTick in our case);
- It includes a script file in the page, using the above URL as its src;
- The script in turn calls the callback function and provides a special object containing all the tweets as a parameter;
- The callback function uses this object to build and show the tweets;
As the search api script is called after page load, there is no waiting for the script to load and hanging of the page in the mean time. This is a true asynchronous javascript solution – a great alternative to AJAX.
Now here is the code that makes this happen:
demo.html
<link rel="stylesheet" type="text/css" href="demo.css" /> <link rel="stylesheet" type="text/css" href="jScrollPane/jScrollPane.css" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript" src="jScrollPane/jquery.mousewheel.js"></script> <script type="text/javascript" src="jScrollPane/jScrollPane-1.2.3.min.js"></script> <script type="text/javascript" src="script.js"></script>
First, we include our demo.css and jScrollPane.css. These style the ticker.
Later we include the jQuery library from Google’s CDN, the mousewheel plugin and the jScrollPane plugin.
Last is script.js, which is shown below:
script.js
var tweetUsers = ['tutorialzine','TechCrunch',
'smashingmag','mashable'];
// The twitter accounts that will be included in the ticker
var buildString = "";
$(document).ready(function(){
// After the page is loaded
$('#twitter-ticker').slideDown('slow');
// Show the ticker
for(var i=0;i<tweetUsers.length;i++)
{
// Build the search api parameters
if(i!=0) buildString+='+OR+';
buildString+='from:'+tweetUsers[i];
}
var fileref = document.createElement('script');
// Creating a new script element
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", "http://search.twitter.com/search.json?q="+buildString+"&callback=TweetTick&rpp=50");
// Setting its src to the search API URL; We provide TweetTick as a callback
document.getElementsByTagName("head")[0].appendChild(fileref);
// Appending it to the head of the page and thus executing it
});
function TweetTick(ob)
{
// This is the callback function
var container=$('#tweet-container');
container.html('');
// Removing the loading gif animation
$(ob.results).each(function(el){
// ob contains all the tweets
var str = ' <div class="tweet">\
<div class="avatar"><a href="http://twitter.com/'+this.from_user+'" target="_blank"><img src="'+this.profile_image_url+'" alt="'+this.from_user+'" /></a></div>\
<div class="user"><a href="http://twitter.com/'+this.from_user+'" target="_blank">'+this.from_user+'</a></div>\
<div class="time">'+relativeTime(this.created_at)+'</div>\
<div class="txt">'+formatTwitString(this.text)+'</div>\
</div>';
container.append(str);
// Adding the tweet to the container
});
container.jScrollPane();
// After all the tweets have been added, create the slidebar
}
function formatTwitString(str)
{
// This function formats the tweet body text
str=' '+str;
str = str.replace(/((ftp|https?):\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?)/gm,'<a href="$1" target="_blank">$1</a>');
// The tweets arrive as plain text, so we replace all the textual URLs with hyperlinks
str = str.replace(/([^\w])\@([\w\-]+)/gm,'$1@<a href="http://twitter.com/$2" target="_blank">$2</a>');
// Replace the mentions
str = str.replace(/([^\w])\#([\w\-]+)/gm,'$1<a href="http://twitter.com/search?q=%23$2" target="_blank">#$2</a>');
// Replace the hashtags
return str;
}
function relativeTime(pastTime)
{
// Generate a JavaScript relative time for the tweets
var origStamp = Date.parse(pastTime);
var curDate = new Date();
var currentStamp = curDate.getTime();
var difference = parseInt((currentStamp - origStamp)/1000);
if(difference < 0) return false;
if(difference <= 5) return "Just now";
if(difference <= 20) return "Seconds ago";
if(difference <= 60) return "A minute ago";
if(difference < 3600) return parseInt(difference/60)+" minutes ago";
if(difference <= 1.5*3600) return "One hour ago";
if(difference < 23.5*3600) return Math.round(difference/3600)+" hours ago";
if(difference < 1.5*24*3600) return "One day ago";
// If the tweet is older than a day, show an absolute date/time value;
var dateArr = pastTime.split(' ');
return dateArr[4].replace(/\:\d+$/,'')+' '+dateArr[2]+' '+dateArr[1]+
(dateArr[3]!=curDate.getFullYear()?' '+dateArr[3]:'');
}
You can see that on line 55 we use the jScrollPane plugin. It creates a handy scrollbar to the right of the tweets. Thanks to the mouseWheel plugin it is also able to detect and scroll the page on mouse wheel movements.
To change the twitter accounts that are shown in the ticker, you’ll need to modify the tweetUsers array.
If you provide two or more twitter names, their tweets will be shown together. Only the 50 most recent tweets from the past 7 days will be returned.
It is worth noting that Twitter puts a maximum limit to the search api’s URLs of 140 characters. This would be sufficient for about 7 twitter user names.
With this the twitter ticker is complete!
Conclusion
Today we used the Twitter Search API to build a handy jQuery Ticker that will show your latest tweets on your blog or site. Possibilities are endless, because no server side code or databases are required and you are free to modify the code any way you see fit.
We are always happy when we are presented with custom modifications of our tutorials.
If you have customized this tutorial, and would like to share it with our readers, fill this form and you may be featured in our twitter stream.







Martin,
Thanks a bunch for this awesome tutorial, implementation, code-sharing and mash-up.
I’d previously cobbled another api mash-up together for my site, but this one will Definitely soon be replacing that.
In your spirit of giving, I commend, and thank you.
Michael
Nice tuts! <3
Can I experiement and change the width such that it is larger?
This is fantastic! No PHP required? Thanks for this awesome tutorial.
***| Follow-UP |***
Works exactly as advertised. All the coding, both html and css is very well structured, and extremely easy to tweak, enabling you to meld it into your overall site design quite nicely.
I had entertained thoughts of replacing the little guy, but for now– I think I’ll keep him. He’s cute enough to have around.
Again Martin, Kudos and Thanks!
Hey
Thanx for this wonderful tutorial
It’s really helpful
I have a question though… I only want to show one tweet at a time… how do I do that?
Many thanx
Greets, Kristel
Thanks for the great comments! Glad you like it.
@ zhu
You can change the width by changing the value at line 21 of demo.css
@ kristel
To show one tweet at a time you’ll need to set rpp=1 on line 25 of script.js. This stands for results per page.
@ Michael
Those are some cool customizations you’ve done there, Michael. It looks great.
Thanx
You don’t know I happy I am with this tutorial
Wow, very nice ^^
Nice widget, thanks!
*wohooo*
Going to use this on my blogs. Kudos for the good tutorial.
I love the explaining illustrations!
hey,
great tut – really useful and works great.
But I’ve got a little question: Why do you use “classic” js on lines 21-28? I tried it with jQuery ()- and it works (Firefox 3.5, Opera 10.00, Chrome 3 (so Safari will do as well) and Internet Explorer 7 and 8 [not 6]).
Thanks and greetings,
Linus Metzler
Great tutorial, very helpful.
Is there a way to display a search query and not a specific user. So the end result will be something like the Search Widget? http://twitter.com/goodies/widget_search
Oh, and thanks a lot for this great tutorial!
How about performance if other JS is used on the site? I just heared that (could be from Chris from CSSTricks) the twitter api is extremly ressource hungry, but maybe I understood something wrong?
keep up the great work!
@ Linus Metzler
jQuery is fantastic in DOM manipulation, AJAX-es and everything else, but its nice to have some plain-old JS from time to time.
@ Roy
Yes, you can show tweets based on a search. Just remove lines 14-19 and change line 25 to your desired search string. You can show tweets in the widget based on search terms, mentions, trending topics or anything you can think of.
You can use this form to generate the query – http://search.twitter.com/advanced
@ LuK
In this case, performance issues are not likely to arise from the twitter API directly, but rather from the callback function.
It could become a problem if your page is action-packed with JS that is run on page load.
If you notice such an issue, you can always lower the results per page setting on line 25 of script.js – this will lighten the burden on the callback.
impressive, very nice work and integration….
thanks for your work, a really impressive and well-done tutorial!
Very slick! Question though… If you had a bunch of users visit your site, wouldn’t this cause you to exceed your twitter API limit? Wouldn’t it in that case make more sense to use a server-side script for this then, so you could cache the results and avoid something like that?
@ Evan Byrne
I couldn’t find the exact limit per hour for twitter’s search API, but you can be assured it is quite high.
Also the limit is IP-bound. This means that no matter how popular your site is, the limit is counted individually for each visitor.
“Yes, you can show tweets based on a search. Just remove lines 14-19 and change line 25 to your desired search string. You can show tweets in the widget based on search terms, mentions, trending topics or anything you can think of.
You can use this form to generate the query – http://search.twitter.com/advanced”
Can you maybe give an example of what exactly the current line looks like, and what the line would look like with the search query inserted?
Because even though you explained it quite clearly, I cannot seem to get it to work. Obviously I’m doing something wrong.
(We are talking about script.js, correct?)
Thanks for a great script.
high quality for this site thx very much ¡¡¡ ^^
@ Beun
Line 25 of script.js should be changed from:
fileref.setAttribute("src", "http://search.twitter.com/search.json?q="+buildString+"&callback=TweetTick&rpp=50");To:
fileref.setAttribute("src", "http://search.twitter.com/search.json?q=YOUR+QUERY+HERE&callback=TweetTick&rpp=50");Change only the q= parameter to your search string. You can also search for a hashtag by setting q=%23MyHashtag. Notice how the # is replaced with %23. It is the same with mentions – just remember to replace the @ with %40
@ Martin
Thanks a lot for the explanation. I now see where I went wrong. It would appear that line 25 in script.js from the downloadable demo.zip, is not the same as line 25 in the explanation at the top of this page.
Thanks!
And If I want to show only the last tweet where I modificate?
Andrei, to show only the last tweet you can change rpp=50 to rpp=1 in script.js on line 25.
working fine thx
Any way to display a feed from a list instead of selecting individual users?
Thanks!
@ TucsonSentinel
After a check with Twitter’s API docs, I found a way to show the list updates instead in the widget.
Remove lines 14-19 of script.js in Step 3 and replace line 25 with:
fileref.setAttribute("src", "http://twitter.com/USERNAME/lists/LISTNAME/statuses.json?callback=TweetTick");Where USERNAME is the owner of the list and LISTNAME is the list itself.
Martin,
Tried that code, but it’s throwing an error “pastTime is undefined” from the mousewheel handler. ??
I found that adding +OR+@USERNAME into the search parameters at line 25 adds RTs & replies into the results – no need to use the entity code. Looking at the list section of the API, it doesn’t look like it’s possible to mix the search & list methods. Or is it?
Thx – this is a really cool script.
Many thx !
Great tutorial. Thank you so much. Can i’ll link you my test?
Awesome tutorial.. It helped me a lot to create this: Shitty Day
@TucsonSentinel
This error might come from the fact that twitter provides LIST information from a different API, and not the SEARCH API that is used by this ticker.
This means, that it is not guaranteed that it follows the same structure, and from the error you reported I think that it indeed does not.
The only way you could make it work with the LIST API is to manually change each variable used in lines 44-49 in script.js (the TweetTick function), so that it corresponds to the new structure of the tweets.
Or you could wait for Twitter to introduce this functionality in the SEARCH API. Should be available once they allow you to search tweets from certain lists in their site’s search.
@simurai
That is awesome. A great design and idea.
Thanks for this excellent tutorial.
How can we change the limit of 7 days for tweets?
@simurai
awesome ! !
Is there a way to show tweets that are older than 7 days?
I’d like to have the ticker show the last 10 tweets regardless of date.
I haven’t found anything in the code…
Thanks.
@ George
Unfortunately, it is not possible to show tweets older than 7 days – this is a limit imposed by twitter for their search API.
Is there any way of creating interval for checking the tweets?
For example, to check the tweets every few minutes, and refresh the list.
And would it cause a problem for performance or something?
Thanx.
var tweetUsers = ['tutorialzine','TechCrunch',
002.'smashingmag','mashable'];
003.// The twitter accounts that will be included in the ticker
when I put my accounts name in there, it still shows the posts from the user which was previously shown? what else do I have to change?
I wanted to say, that sometimes not all tweets appear in the search. http://apiwiki.twitter.com/Twitter-REST-API-Method:-statuses-user_timeline might be a hint?
this is quite cool
thanks for sharing this nice one!
I have something similar on my website, but to let you combine multiple accounts this wins hands down.
Great tutorial.
looks gr8….will surely try this..
NOT compatible with Opera browser.