Create a Slick iPhone/Mobile Interface from any RSS Feed

Avatar of Chris Coyier
Chris Coyier on

Get affordable and hassle-free WordPress hosting plans with Cloudwaysstart your free trial today.

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