Grow your CSS skills. Land your dream job.

Create a Slick iPhone/Mobile Interface from any RSS Feed

Published by Chris Coyier

We are going to create a web page that is formatted specifically for the iPhone (but would presumably be good for other mobile devices as well). This web page will dynamically fill itself with content from any RSS feed that you give it. The interface is going to be built to be easy to use on a mobile device, with large "touchable" areas and nice (jQuery) animations that whisk you between articles.

VIEW DEMO

Let's get started!

 

1. Create the iPhone Environment

Some mobile interfaces just let the "wrap" of the site go 100% wide, which should theoretically fill the width of whatever browser being used (like this one). For a variety of reasons, we need to set a fixed pixel width for our wrap. The iPhone is 320px wide in normal portrait mode, so let's accommodate to that. We'll need to use a "viewport" meta tag in order to get our 320px wrap to view nicely in the iPhone. Go ahead and create an index.php file in a new project directory on your server. The markup is going to start off 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" />
	<meta name="viewport" content="width=320" />

	<title>iPhone Interface by CSS-Tricks</title>
	
	<link rel="stylesheet" type="text/css" href="style.css" />
</head>

<body>

	<div id="page-wrap">
	</div>

</body>

</html>

Other than our typical reset and toolbox stuff, all we need at this point is our page-wrap declared in our CSS. Let's make it 310px wide with 5px of padding on each edge to keep text from touching the edges.

div#page-wrap { width: 310px; padding: 0 5px; margin: 0px auto; }

 

2. Pull in the RSS Feed

Let's get right to it, shall we? There are a couple of free options for pulling in RSS feeds and displaying HTML. The hip and cool one is SimplePie. FeedForAll also makes a free RSS Feed Parser they call RSS2HTML. I actually originally created this using RSS2HTML and it worked fine, but in the name of being hipper and cooler, I switched it to SimplePie. SimplePie has some pretty badass extra features that you could potentially use (like easily pulling multiple feeds), so I figured that would be best for ya'll.

Go download SimplePie and put the simplepic.inc file in the same directory on your server as your index.php file.

Place this PHP at the top of your index.php file:

<?php
	require_once('simplepie.inc');
	
	// CHANGE THE FEED ADDRESS BELOW - THAT'S IT!
	$feed = new SimplePie('http://feeds.feedburner.com/CssTricks');
	
	$feed->handle_content_type();
	
	$total_articles = 3;
	
	for ($x = 0; $x < $feed->get_item_quantity($total_articles); $x++)
	{
		$first_items[] = $feed->get_item($x);
	}
?>

Notice the bit about the total articles. We wouldn't normally need to go through all this extra stuff. With SimplePie, normally getting a feed as as simple as this:

$feed = new SimplePie(css-tricks.com);

Just that bit will go get the feed (notice it's not even an RSS feed, it will auto-detect). But doing it that way will get every single item in the feed. In this tutorial, we specifically only want to get 3 articles, so thats what the total_articles bit is all about.

Not that we have our data, let's pause for a moment before we go spitting it out as HTML and think about how we want to display it.

 

3. Creating the Front Page: Headlines Only

The last thing we would want to do with our new feed data is just barf it out all onto our new "front page". That wouldn't be very iPhone-like of us, would it? Since we have precious little screen real estate, lets list only the headlines and dates on the front page. The idea will be to create essentially large buttons for each of the three latest articles. Clicking those buttons will then take us to the corresponding article to read. Here is the desired interface:

To achieve this, this is the desired HTML output for each article:

<div class="headline">
   <h2>  ... article title here ...  </h2>
   <p> .... date here ... </p>
</div>
<img src="bottom.png" alt="" />

That image included at the bottom is how we will achieve the bottom of the rounded corners effect we are going for. The top rounded corners will be part of the background image in the "headline" div. The background image needs be pretty tall so it can grow to accommodate large headlines, but the bottom image can be pretty short. We will also include the "button" as a part of this background image. Here they are:

These are alpha-transparent PNG's. No worries there, the Safari browser on the iPhone supports them. We will be just over a white background here, so the effect a bit lost, but if chose to put a texture or background graphic, these images would lay nicely over top.

Now in order to output these three headlines in with in our schemed-up HTML template, we need to do a little PHP foreach loop like so:

<?php
	foreach ($first_items as $item)
	{
		echo '<div class="headline"><h2>' . $item->get_title() . '</h2><p style="margin: 0;">' . $item->get_date('j M Y') . '</p></div><img src="images/bottom.png" alt="" style="margin: 0 0 10px 5px;" />';
	}
?>

Here is the related CSS:

.headline           { background: url(images/headline-bg.png) top center no-repeat;
			padding: 3px 68px 0 13px; min-height: 60px; }

 

4. Creating the Article Pages: jQuery Slider Style

We could just create a subpage for our site and have that load up and display the article when you click, but that wouldn't be any fun! We are trying to create a slick interface here. One that is fast and slides around and stuff!

This is where the jQuery magic comes in. What we want to happen is when you click on one of our big headline buttons, the page slides over to reveal the entire article. The ol' Tap-n-Slide, as I like to call it:

To make this happen, we are going to use the guiding principal behind all javascript sliders: masking. The idea is this:

What we have here is a big wide content area the width of four times our homepage. Residing inside is the homepage along with three more blocks containing each of our three articles. These are floated to the left to keep them in a nice top-aligned row. We "mask" the content area by putting it inside another div and hiding the spillover (overflow: hidden; in CSS speak).

In order to build this in our markup, we need to do another loop in much the same fashion as we build our Front Page. Here is the progress so far:

<body>

	<div id="page-wrap">
	
		<div id="slider">
				
			<div id="mask">
				
				<div id="mainMenu">
					<?php
						foreach ($first_items as $item)
						{
							echo '<div class="headline"><h2>' . $item->get_title() . '</h2><p style="margin: 0;">' . $item->get_date('j M Y') . '</p></div><img src="images/bottom.png" alt="" style="margin: 0 0 10px 5px;" />';
						}
					?>
				</div>
				
				<?php
					foreach ($first_items as $item)
					{
						echo '<div class="article-text"><h1><a href="' . $item->get_permalink() .'">' . $item->get_title() . '</a></h1><p>' . $item->get_date('j M Y') . '</p><p>' . $item->get_content() . '</p></div>';
					}
				?>
				
			</div>
			
		</div>
		
	</div>
	
</body>

This code will first run a loop to build the Front Page, and then build three Article Pages (each a div of class "article-text"). Notice in our loop this time we not only grab the title and date, but we link the title to the permalink of the original article and we grab the full content as well.

All of this will be loaded when the page is loaded, but of course you will only see the Front Page at first, because the other articles are hidden behind the mask.

Here is the related CSS to make that happen:

#slider 		{ width: 320px; overflow: hidden; position: relative; }
#mask			{ width: 1280px; position: relative; left: 0px;}
#mainMenu		{ width: 320px; float: left; }
.article-text		{ width: 320px; float: left; overflow: hidden; }

So how are we going to ever see these articles, if they are hidden behind the mask? This is where the jQuery magic begins!

If we "slide" our content area to the left we can hide the Front Page and reveal an article. The amount that we need to slide to the left depends on which headline we click on. If we click on the first headline, we need to slide to the left 320px (the width of one viewable area). If we click on the second headline, we need to slide over two viewable areas or 640px. Likewise the third, 960px. These will need to be negative values, since "left" on the web generally means negative values. Notice the relative positioning applied to the slider area, this is necessary for the left value to have any meaning and actually do any sliding.

Here is the jQuery stuff you can add in the head section of your index.php file to make this happen.

<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){

	$('.headline:eq(0)').click(function() {
		$("#mask").animate({
			left: "-320px"
		});
	});
	
	$('.headline:eq(1)').click(function() {
		$("#mask").animate({
			left: "-640px"
		});
	});
	
	$('.headline:eq(2)').click(function() {
		$("#mask").animate({
			left: "-960px"
		});
	});

});
</script>

 

6. Adding Some Flair

We're almost there folks. We got ourselfs a fully functioning interface, but it could work a little nicer... For one thing, how do we get back to the Front Page when we are done reading and article? Let's solve that one first. Longer articles can take quite a bit of finger-scrollin' on a mobile phone, so we should definitely have a "back" button at the bottom of the article. But let's say you tapped on an article by accident, and need to get back to the Front Page right away, we should have a "back" button at the top too.

For the top "back" button, let's actually include the title of the RSS feed at the top of the page and make that function as the "back" button.

<h1 id="home"><?php echo $feed->get_title(); ?></h1>

We'll use that ID value to target it with jQuery later. At the bottom of the post, let's make it even more obvious by including a big arrow image.

Then we'll include it in every single article, by making it a part of the loop:

<?php
	foreach ($first_items as $item)
	{
		echo '<div class="article-text"><h1></h1><p>' . $item->get_date('j M Y') . '</p><p>' . $item->get_content() . '</p><img src="images/backbutton.png" alt="Back" /></div>';
	}
?>

Now we need some jQuery to "slide" back to the Front Page when either of these things is clicked. But hold up... if you are at the bottom of the page when this happens, you are going to scroll back to a empty white page. You can always scroll back up, but that feels a little weird. We can actually use jQuery to scroll back up for us. Let's include that in the functions:

$('.back').click(function() {
	$("#mask").animate({
		left: "0px"
	});
	$('html, body').animate({scrollTop:0}, 'slow'); 
});

$('#home').click(function() {
	$("#mask").animate({
		left: "0px"
	});
	$('html, body').animate({scrollTop:0}, 'slow'); 
});

Issue: iPhone doesn't seem to respect the scrollTop thing, which is a bummer. If anyone has any ideas on how to fix this, do let me know!

Other little stuff:

  • Each article div has overflow set to hidden as well. This is to prevent images that may be wider than this area to keep from spilling over onto the other articles. This is one solution which seemed to work fine for me. You may want to scale down your images if that makes more sense for you.
  • Remember to style things up as you like them! If your feed uses <h3> tags, you are going to get <h3> tags back, so remember to add CSS for these things! My feed also has code snippets which I like to place in <pre> tags, this will cause breakouts beyond the 320px. This can be handled by setting a static width and using overflow: auto, or forcing the pre tag back to white-space: normal; - so it wraps.
  • Article titles, links, dates, and content aren't the only things you can pull from an RSS feed. SimplePie provides access to an absolute ton of other data. Check out their API information for a list of other variables you can play with. There even cool ones like buttons for social bookmarking and different ways to subscribe to content. I also like the one for pulling the favicon of the feed. Maybe someone could put together an multi-feed interface for lots of different CSS blogs and put them into one, identifying the source by the favicon!

 

OK. What if I just want to download this thing and make it work for my site?

First of all:

 

Download Files

 

Upload the files to your server. Open the index.php file and change the link on the 5th line to your own RSS link. That's it!

Of course you are welcome to customize this and use it for whatever you want. I always appreciate links back and would love to see your work.

 

View Demo

 

Comments

  1. Hm, this really is a great tutorial. I was already thinking of creating a WordPress theme that allows this ol’ tap N slide thing, what do you think, do you think there is a demand for this kind of theme? What about also developing a plugin that detects iPhones and automatically applies this specific theme?

    Oh I would have great ideas, but not enough power to do so. I could – I think – if I used your “sceleton” for the theme, since I know how to integrate WordPress content into a theme, so I wouldn’t use the SimplePie codes, but rather the WordPress WP-commands.
    Great, really!

  2. Thanks for the great post ;D

  3. LINK

    Okay, seems like there is something out like this. Yet a “unique” iPhone wordpress theme isn’t out there, I did some research and failed to find one…

  4. Kevin Seer

    Nice….but eaiser just to use one of the free feed convertor services – I use RSS Builder for the iPhone – http://www.thesmespace.com/smeutils/feed – converts any RSS or Atom feed to a slick iPhone interface

  5. @Phil: Good idea! I’ve seen that plugin before and have actually used it briefly. It does a great job. One of the advantages of doing it this way though is that it’s NOT WordPress dependent, so you can use any feed whatesover (or even multiple feeds)

    @Kevin: That’s pretty cool too, but it’s returning only partial feeds and isn’t hosted on your own site, both things I would think most site owners would want.

  6. Chris, if you want me to have a look into this and maybe turn it into a WordPress theme that then could be custimized by CSS and would offer all WordPress functions like comments, let me know. Contact me via my blog or AIM… I can’t do the jQuery thing, so I’d have to use yours as a basis.
    I’m sure some users would enjoy this as a theme, since they want their readership to have full functionality.

  7. I love this, it’s wicked smooth and useful. I’ve been looking for a good mobile interface for my site. This may be the one.
    Thanks Chris

  8. That is a bit complex but I think it just get it.

  9. Really great stuff here, Chris. A deceptively simple interface mounted on some elegant tools all working together — what more could you want?

  10. 10x – really enlightening info.

  11. Great tutorial. Didn’t donate but I did visit a few sponsors I found interesting.

  12. Permalink to comment#

    Really cool, and I’ll probably work on putting this together on my site soon. One thing I may play with changing is to hide the posts (display: none). As a user taps on a given post, show the post and then initiate the slide. That way the animation never shows other posts going by in the background.

    Nice work!

  13. Hey Rob,

    That is a really good idea, using display: none on the other articles. I don’t mind the sliding so much, but I do mind how the homepage has a huge vertical scroll on it for seemingly no reason when you first get to the page. I think this would solve that!

  14. Amazing….. Your tutorial will improve the source code for the next net-generation like iphone-user ;)

    Ralph

  15. Interesting way to create a mobile page. I tried this and have viewed on my Blackjack II. Unfortunately, this isn’t a touch screen — so I really don’t know what it is doing on those mobile devices.

    On my Blackjack, the main background img (with selection button) is not seen. And, of course, my browser is a downsized MSIE, so the additional content on the slide portion is found wrapped underneath the main headlines.

    I might tweak a bit to see what I do with the missing background and selection buttons for a non-touch screen. But it’s a nice go. I don’t think I’m going to keep it as it is not “best practice” for all mobile devices. But worth a try.

    Thanks much

  16. Hey Chris,

    Great tutorial! Just a couple of things,

    Why wouldn’t you do an each() instead of headline:eq(1), etc?

    Secondly, I dunno about anybody elses’ (it’d be just my luck… have had the shoddiest luck with mine), but my iPhone 3G displays the slide really laggy… Kinda jolts across, and if I do too much at once it just skips the animation entirely!

    • I have significantly improved this code since this original release. I’ll probably post something about it eventually… If you want the code, feel free to snoop around the new iPhone interface around here or email me for the whole package.

    • Even your current one! But I’ll surely email you :).

  17. Permalink to comment#

    Thanks Chris, this is the best iphone UIE article i have ever since in these days.
    Cheers!

  18. Permalink to comment#

    Thanks Chris for this superb tutorial. SimplePie looks promising.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".