Building a Better Blogroll: Dynamic Fun with SimplePie and jQuery
A traditional blogroll is a simple list of other sites, often in the sidebar, that are related, owned by, or otherwise friendly to the home site. Blogrolls are a great idea and on-point with the spirit of blogging, but how is a casual reader to know if any of these sites are truly of interest? Let’s improve upon the concept of a blogroll by not just listing sites, but dynamically pulling recent headlines from them, and using some fun jQuery animation.
Step 1 – The Idea and the Technologies
For our example, we will be using the TUTS family of sites. The idea here is to build a “widget” (for lack of a better term). Along the top of our widget will be a line of logos from each of the different sites in our blogroll. The TUTS family have lovely simple block logos which will make this easy, but the concept could be adapted to any logo. Each of the logos will act as “tabs” or buttons which when clicked, will display recent headlines from the respective site. Here is quick overview of the technologies we will use
- Of course we will be using XHTML/CSS to build and style the widget.
- We will use jQuery and the Coda Slider plugin for the fun animation.
- The recent headlines will be dynamically pulled using PHP and SimplePie.
Because of the use of PHP, you won’t be able to download the source code, open it up on your local machine, and view the demo. You’ll need to either run PHP on your local machine, or upload it to your own server to play with it.
Step 2 – Designing
Design first, code later. I find the results are always better this way. A little playing around in Photoshop and we have a simple-yet-modern design to work with:

Note the use of guides. Being as clean and accurate with your design work is just as valuable as being clean and accurate with your code! Note that the PSD files will be included in this demo.
I don’t want to go into a ton of detail about how all the design work was done and how all the images were sliced out. Instead lets take a look at each one and I’ll quickly explain.
|
Image for the background texture. Repeats across the entire body element. |
|
Image for the PSDTUTS tab. Bottom half is for “on” position, top half is for “off” position. |
|
Image for the VECTORTUTS tab. Bottom half is for “on” position, top half is for “off” position. |
|
Image for the NETTUTS tab. Bottom half is for “on” position, top half is for “off” position. |
|
Image for the AUDIOTUTS tab. Bottom half is for “on” position, top half is for “off” position. |
|
Image for the “body” of the widget. This can repeat vertically so it can grow as tall as needed. |
|
Image for the bottom of the widget. |
|
Image for the “next” button, for moving ahead to the next tab. |
|
Image for the “previous” button, for moving back to the previous tab. |
Step 2 – Downloading the Files
Normally we might start by coding the XHTML/CSS we need for the widget first. That is usually the best way to go so you can ensure clean and semantic markup. However, for this example, I believe it will be easiest for us to download all the components we need to make this thing work, and then code around that. This is because the jQuery plugin “Coda Slider” we are using has a specific HTML structure it likes.
You’ll need a home directory for this project, so go ahead and create a new folder. Then create an index.php file, a style.css file, and we’ll need folders for images, inc, and js. More organization! Then download the following things:
- Download the latest jQuery to your js folder and include in your head section.
- Download the Coda Slider plugin and include the plugin file, as well as the easing and easing compatibility JavaScript files in your head section.
- Download SimplePie. Put the simplepie.inc file in your inc folder. You don’t need to include anything on the page for this just yet, we’ll get into this later.
When you are through, the top of your index.php file should be like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>A Better Blogroll</title> <link rel="stylesheet" type="text/css" href="style.css" /> <script src='js/jquery-1.2.6.min.js' type='text/javascript'></script> <script src="js/jquery-easing.1.2.js" type='text/javascript'></script> <script src="js/jquery-easing-compatibility.1.2.js" type='text/javascript'></script> <script src="js/coda-slider.1.1.1.js" type='text/javascript'></script> </head>
Step 3 – The Markup
If you pop open the code for the demo that comes with the Coda Slider, you’ll see there is quite a few “wrapping” DIVs going on. The whole slider is wrapped in one then all of the panels are wrapped in one, then each panel is wrapped and there is even an inner wrapper inside each panel. Looks a bit like “DIVitis” (The plague of amateur coders using way more DIVs than necessary). Fret not, however. While I can’t argue that there is a lot of DIVs going on here, each of them serves a purpose unique to the slider and is necessary for its form and function. In fact, our unique design complicates things even more and requires the use of a few more DIVs here and there.
Here is the markup for the rest of the page, sans the actual content for each of the panels:
<body> <div id="blogSliderWrap"> <div id="blogSlider"> <div class="innerWrap"> <div class="panelContainer"> <div class="panel" title="PSDTUTS"> <div class="wrapper"> <!-- content for panel --> </div> </div> <div class="panel" title="NETTUTS"> <div class="wrapper"> <!-- content for panel --> </div> </div> <div class="panel" title="VECTORTUTS"> <div class="wrapper"> <!-- content for panel --> </div> </div> <div class="panel" title="AUDIOTUTS"> <div class="wrapper"> <!-- content for panel --> </div> </div> </div> </div> </div> <div id="push"></div> </div> </body> </html>
Notice how there is no markup for the list of logos at the top? That markup gets dynamically generated by the plugin based on how many panel it detects. It also gives each of the list items a unique class name. We will use these to apply the images we created. Pretty fancy eh? This makes it very easy to add and remove panels from this slider in the future. If you want a peak at the code it creates, you can use something like Firebug to view the source after it has been rendered:

Step 4 – The CSS
Now that we have the markup squared away, we can set about to styling. Again, rather than go through every single selector here, I’ll just show you the entire CSS file and then below I’ll go over some of the important points. There is also some commenting within the CSS you may find of interest.
/*
GENERIC RESET & BASIC STRUCTURE
*/
* { margin: 0; padding: 0; }
body { font-family: Verdana, Arial, Helvetica, sans-serif;
background: url(images/body-bg.jpg); font-size: 11px; }
a { /* remove the dotted outlines when clicking tabs */
outline: none; text-decoration: none; }
ul { list-style: none; }
/*
WIDGET STRUCTURE
*/
#blogSliderWrap { width: 320px; margin: 50px auto;
background: url(images/widget-bottom-bg.jpg) 7px bottom no-repeat;
padding-bottom: 50px; position: relative; }
#blogSlider { margin-left: 15px; padding: 25px 18px 0px 18px; width: 263px;
background: url(images/widget-middle-bg.jpg) center center repeat-y; }
.stripViewer { position: relative; overflow: hidden; clear: both; }
.stripViewer .panelContainer { position: relative; left: 0px; top: 0px; }
.stripViewer .panelContainer .panel { float: left; position: relative; width: 280px; }
.wrapper { padding: 10px; }
.innerWrap { width: 273px; overflow: hidden; }
#push { height: 35px; }
/*
MAIN TABBED NAVIGATION
*/
.stripNav { margin-left: 22px; position: relative; top: 18px; z-index: 99;
width: 285px; }
.stripNav ul li { float: left; }
.stripNav li a { /* Generic "CSS image replacement" */
display: block; height: 18px; text-indent: -9999px; }
/* The below class names are auto-generated by the JavaScript */
.stripNav li.tab1 a { background: url(images/tab-psdtuts.jpg) top center no-repeat; width: 63px; }
.stripNav li.tab2 a { background: url(images/tab-nettuts.jpg) top center no-repeat; width: 63px; }
.stripNav li.tab3 a { background: url(images/tab-vectortuts.jpg) top center no-repeat; width: 85px; }
.stripNav li.tab4 a { background: url(images/tab-audiotuts.jpg) top center no-repeat; width: 73px; }
.stripNav li a:hover,
.stripNav li a:active,
.stripNav li a:focus { /* Restore focus styling that we removed when we removed outlines */
background-position: top center; }
/* It is neccessary to repeat the image paths here */
.stripNav li.tab1 a.current { background: url(images/tab-psdtuts.jpg) bottom center no-repeat; }
.stripNav li.tab2 a.current { background: url(images/tab-nettuts.jpg) bottom center no-repeat; }
.stripNav li.tab3 a.current { background: url(images/tab-vectortuts.jpg) bottom center no-repeat; }
.stripNav li.tab4 a.current { background: url(images/tab-audiotuts.jpg) bottom center no-repeat; }
/*
SUB NAVIGATION
*/
.stripNavL a, .stripNavR a { display: block; position: absolute; width: 75px;
height: 22px; text-indent: -9999px; }
.stripNavL a { bottom: 35px; left: 45px; background: url(images/previous.png); }
.stripNavR a { bottom: 35px; right: 45px; background: url(images/next.png);
}
/*
HEADLINES STYLING
*/
.panel ul { width: 240px; }
.panel ul li a { border-bottom: 1px solid #C1B599; color: #303030;
display: block; padding: 7px 10px; }
.panel ul li:last-child a { /* Remove bottom border on last list item
Hooray for pseudo selectors! */
border: none; }
/* Unique rollover colors for each list */
.panel ul#psd-list li a:hover { background: #b20202; color: white; }
.panel ul#net-list li a:hover { background: #4a8c7f; color: white; }
.panel ul#vector-list li a:hover { background: #1f5293; color: white; }
.panel ul#audio-list li a:hover { background: #4f7c11; color: white; }
- The outer-most wrap (#blogSliderWrap) contains the background image for the bottom of the widget. Laying on top of that is the “expandable” part of widget, which contains the vertically-repeatable background image (#blogSlider)
- In order to keep the content from appearing to “fly in” from outside of the main white area, yet another wrap was needed (.innerWrap) that slims the inside down even further to prevent that. This is unique to our super-cool drop shadowed design.
- As I mentioned earlier, the markup for the main navigation is generated on-the-fly by the JavaScript, but that doesn’t mean we can’t still style it with CSS. The style for (.stripNav) uses relative positioning to kick it over into place as well as ensure that it is on top of all over page elements.
- We use the unique class names the JavaScript gives us to use basic CSS image replacement and apply our images to each tab. Note that shared attributes (like height) are applied generically while unique attributes (like width) are applied specifically.
- The JavaScript also auto-generates two special page elements for moving ahead a single tab or moving backward a single tab. We apply images and positioning to these as well
- Ultimately, each panel will contain and unordered list of headlines. We will give each of these a unique ID. For a bonus nice touch, each of them will have a rollover color that matches the logo color of the originating site.
Step 5 – Activating the Slider
Now with the images, markup, and CSS all in place, we can kick off the slider. Include the following JavaScript at the bottom of your head section.
<script type='text/javascript'>
$(function () {
$("#blogSlider").codaSlider();
});
</script>
Now we have a perfectly functional slider, with nothing in it.

Step 6 – Pulling the Headlines with SimplePie
SimplePie is a PHP feed parser which makes it pretty darn easy to pull in RSS feeds and use the content as we wish. In our example, all we need are the headlines and links, but pulling the feed is always the same regardless of what you use.
At the very top of your index.php file, include the following PHP code:
<?php
require_once('inc/simplepie.inc');
$total_articles = 10;
$psdtutsfeed = new SimplePie('http://feeds.feedburner.com/psdtuts');
$psdtutsfeed->handle_content_type();
for ($x = 0; $x < $psdtutsfeed->get_item_quantity($total_articles); $x )
{
$psdtutsarticles[] = $psdtutsfeed->get_item($x);
}
?>
This code will go out and get the RSS feed from the main PSDTUTS RSS feed (http://feeds.feedburner.com/psdtuts). Then we create an array of the 10 most recent headlines. Now down in our “panel” for PSDTUTS, we’ll need to cycle through this array and echo out the linked headlines. Here is the new code for the PSDTUTS panel:
<div class="panel" title="PSDTUTS">
<div class="wrapper">
<ul id="psd-list">
<?php
foreach ($psdtutsarticles as $item)
{
echo '<li><a href="' . $item->get_link() . '">' . $item->get_title() . '</a></li>';
}
?>
</ul>
</div>
</div>
You can guess where we need to go from here… We need to do the exact same thing for each of our four panels. No need to list all the code out here, as all we do is create new variables for each of the feeds, pull them in, and create new arrays for each of those feeds. Then we loop through each of those new arrays just like we did for PSDTUTS to echo out the linked headlines.
Notice how the unordered list we used for the PSDTUTS headlines had a unique ID of “psd-list”. That isn’t entirely necessary, but I have used that as a hook in this example to apply a different rollover color for each headline list.
Our widget is now nearly complete!

Step 7 – Fixing up IE
Despite being fully valid code, both IE6 and IE7 were showing some quirks with the background images. Oh well, our super-cool drop shadow isn’t in any way necessary. We can leave it in place as “progressive enhancement” for folks with quality modern browsers and pull it out for IE, leaving just a simple white box.
Include an IE-Only Stylesheet in your head section like so:
<!--[if IE]> <link rel="stylesheet" type="text/css" href="style-ie.css" /> <![endif]-->
Then create the style-ie.css file in your home directory and include the following:
#blogSliderWrap {
background: white;
width: 285px;
position: relative;
overflow: hidden;
}
#blogSlider {
background: white;
width: 285px;
padding: 0;
margin: 0;
}
.stripNav {
margin: 0;
top: 0px;
}
Now everything is A-OK in Internet Explorer. The background is simply just white:

So there you have it, a better blogroll for all! Clearly, the technologies presented here can be used for all kinds of interesting things beyond a simple blogroll. The slider is a fantastic plugin that could used for a photo gallery, a portfolio, step-by-step instructions, or any number of applications. The ability to pull in RSS feeds to use on web pages is also very powerful (and potentially abuse-able). See the SimplePie documentation for all you can do with it, and remember to use it for the powers of good!



Is there a prize for the most annoying CSS layout ever? Yours is a contender. Otherwise I like the post.
I use the coda slider to separate a big form in six steps. How I can block the effect if the input data in one step isnt correct? I mean… the user fill the step one and it has and error in one field and I dont want to pass to the second step until the data is correct. How can implement this???
thanks
PD: sorry for my english… Im writting from Argentina
Pelé é o melhor que Maradona !!
Brazil !!
Awesome tutorial
I love the slider
Great !
how can you make it slide automatically ?
thanks !
Awesome tutorial i will try it soon thanks
this tut is awesome… but it will take me exactly a year and a day to figure this out (since i have a coda slider on the index and i’m already getting a feeling that its going to conflict)… not too mention i dont even know how to adjust the settings on my current slider.
thanks for the write up though
this is exactly what i was looking for but i can’t seem to get it to work. I’m getting:
Invalid argument supplied for foreach()
I’m running wordpress and have tried with and without the simplepie plugins.
Anyone able to help?
I was actually impressed with a design. Nice job done.…Thanks!
Ive been wanting to try this out, but Im already using a featured content slider using the coda slider plugin. Will this not conflict with my featured coda slider?
Thanks for this tut, its similar to what i’m looking for
I was wondering if you can use this to showcase content for each link such as home, about, services etc?
Also is there a way to make it so the height or the content box shrinks or grows to match the amount of content thats inside each section/tab instead of having the same height for all the tabs?
Thanks bro!
You Rock!
For anyone who is trying this. The reason that IE strips out the background is because of the ‘repeat-y’ on the middle bg image. It will repeat anyway and so just take it out and everything is dandy.
Matt
please please some one upload or email me the full version + php for rss reading because i try to add php and did not work
here is my email
silu44@gmail.com
does anyone know how to change the class names to be something other than PSDTUTS, NETTUTS, VECTORTUTS, and AUDIOTUTS? When my pointer is above anywhere in each panel, I get rollover text with the name displaying. I think this is generated by the Javascript. Can anyone help please??
Awesome tute! Thanks heaps for this. I used this tut and some other info out there to get my wordpress feed into a spry accordian on my homepage. it was super easy in the end, I used a script off the simple pie site to truncate the data at 180 characters. here is the result http://www.passionfruitdesign.com.au/index.php
Chris creates amazing plugins
Chris
Thanks a lot for the great tutorial. Could you pls tell me how if I want to store the news like a post and comment on it without using any CMS application.
lol this could be done only with some css, theres no need for this design rofl
thanks i really apreciate this script
i added to my personal list in http://ajaxshake.com
great tutorial.thanks a lot.
Wow…easy and effective…great job
There’s a little snag in your for loop …
for ($x = 0; $x get_item_quantity($total_articles); $x
The index needs to increment … so it would actually be …
for ($x = 0; $x get_item_quantity($total_articles); $x++
:-)
very good guide will be useful for me.
no use IE6
Awesome tutorial i will try it, easy and simple