A Simple AJAX Driven Website with jQuery + PHP

Written by Kevin Liew on 08 Jul 2009
399,225 Views • Tutorials


AJAX is abbrieviated from Asynchrounous javascript and XML. It's not a new technology, but the implementation of a group of technologies to achieve a seamless interaction between client and server.

Typically, xhtml and css to present the information, javascript is used to handle user interactions, and a server side language to perform the users' requests (and normally return data in XML format, in this tutorial, we won't do that), and it all is happening in the background using the Javascript XMLHttpRequest. Javascript plays a main role tie all these technologies together and create the asynchronous interaction between client ans server.

AHAH (Asynchrounous HTML and HTTP) is a subset of AJAX which is another technique, Inspite of retreiving XML, AHAH is retreiving HTML content. Both of them are basically the same, the only difference is the content it returns. Generally, most people will simply call it AJAX, but technically, we should call it AHAH. In this tutorial, AHAH is used.

The Good, Bad and Solutions

The Goodies:

  • Reduce connections and bandwidth to the server, images, scripts, stylesheets only need to be downloaded once
  • Reduce loading timew. User doesnt have to load pages again and again, it all happens in a same page!
  • Increase responsiveness and end user experiences.

The Badies:

  • Browser Back button. AJAX web pages cannot connect with browser history engine. If you clicked on back button, you can't navigate those AJAX content.
  • Bookmark will not work on AJAX webpages. Due to the dynamic content, you might bookmark the homepage instead of the desired page.
  • Javascript is needed. To run AJAX based website, your browser need to have javascript enabled.

The Solutions:

AJAX is not a perfect technology, but some of the limitations can be overcame with some simple solutions. I found this very userful plugin called jquery.history.js. It solves Browser Back Button. For the bookmark problem, we can solve it by appending a hash value in the end of the url.

For the last one - javascript, we are going to ignore it. It can be done but I want to keep this tutorial simple.

And, of course, you'll need a good web server as well, if you're hunting for a web hosting company, you can click here to read reviews about the best web hosting out there! iPage Review


You will need the following items and environment to run this script


I will provide two versions of HTML code. The first one is the most basic elements you will need to get it working. And the last one is the one I created with some design

Simplified versions
	<li><a href="#page1" rel="ajax">Home</a></li> 
	<li><a href="#page2" rel="ajax">Portfolio</a></li> 
	<li><a href="#page3" rel="ajax">About</a></li>
	<li><a href="#page4" rel="ajax">Contact</a></li>

<div class="loading"></div>

<div id="content">
<!-- Ajax Content -->

2. CSS

This is really really simple, just have to keep the loading and content hidden

#loading {
	background: url(images/load.gif) no-repeat;
#content {

3. Javascript

I have added comments in every single lines of the code.

$(document).ready(function () {
	//Check if url hash value exists (for bookmark)
	//highlight the selected link
	$('a[href=' + document.location.hash + ']').addClass('selected');
	//Seearch for link with REL set to ajax
	$('a[rel=ajax]').click(function () {
		//grab the full url
		var hash = this.href;
		//remove the # value
		hash = hash.replace(/^.*#/, '');
		//for back button
	 	//clear the selected class and add the class class to the selected link
	 	//hide the content and show the progress bar
	 	//run the ajax
		//cancel the anchor tag behaviour
		return false;

function pageload(hash) {
	//if hash value exists, run the ajax
	if (hash) getPage();    
function getPage() {
	//generate the parameter for the php script
	var data = 'page=' + document.location.hash.replace(/^.*#/, '');
		url: "loader.php",	
		type: "GET",		
		data: data,		
		cache: false,
		success: function (html) {	
			//hide the progress bar
			//add the content retrieved from ajax and put it in the #content div
			//display the body with fadeIn transition

4. PHP

We will not go further on PHP code, this time, I'm using a basic switch to grab the content. The content for the page is being assigned to a variable called "page". And the last line, output the content.

To debug the php script, you can access it by passing data into it, for example:


It should display the content for page1. If you know about php and database, you can store the content in the database and retrieve it. Make a simple form to edit the content and BANG... you got yourself a customized content management system.


//Get the page parameter from the url
switch($_GET['page'])  {
	case 'page1' : $page = 'Page 1'; 
	case 'page2' : $page = 'Page 2'; 
	case 'page3' : $page = 'Page 3'; 
	case 'page4' : $page = 'Page 4'; 
echo $page;


That's it. Make sure you check out the demo and download the source code and play with it. If you have created your own, feel free to drop your link in the comment section to show off! : )

Last but not least, I need your support :) If you like this article, please help me to promote it by adding this post to your bookmark. Or you can subscribe to my RSS for more jQuery tutorial and design inspiration posts! Thanks!

Demo 1Demo 2Download
Join the discussion

Comments will be moderated and rel="nofollow" will be added to all links. You can wrap your coding with [code][/code] to make use of built-in syntax highlighter.

Megan 13 years ago
hello .... auhhmm .... how can i preview my default: in switch statement? is that any function to do this
Kevin Liew Admin 13 years ago
In this example, there is no default, but you can add it:

//Get the page parameter from the url
switch($_GET['page']) {
case '#page1' : $page = 'Page 1';
case '#page2' : $page = 'Page 2';
case '#page3' : $page = 'Page 3';
case '#page4' : $page = 'Page 4';
default : $page = 'Page 1';
echo $page;
Megan 13 years ago
hello sir, i am asking for the preview of my default not the switch code i mean it shows on my page if i browse it.
Sumit Thakkar 13 years ago
It doesn't work in chrome...Any help would be appreciated.

Kevin Liew Admin 13 years ago
Not sure what's wrong. It works in mine. Did you try the demo?
Ian Venskus 13 years ago
Just finished up this project:
using this tutorial. Thank you very much!

We made a lot of adjustments, and used Jquery Address instead of history. We also made it so the loader file uses includes, that way the code and file structure is much cleaner. We did add document.title to change the title tag of the document as well. I'm sure there is a better way to do this using an XML site map, but this works for now.

This also makes only one request to the server, so there's no chance of a page loading and then reloading again.

The javascript code can be found here: http://www.rayreich.com/

Thanks again for this tutorial!
matthew 13 years ago
hey, thanks for this. i changed the loader to includes but in safari and chrome, changing page sometimes requires two clicks. any ideas or is this happening to anyone else?
Ian Venskus 13 years ago
Hi Matthew,

We've changed the the hide and show call to have it all be inside of the onChange function instead of in the click function. This will allow it to work in all instances.

There are also a few things that need to be done for the deeplink redirect and the hash. I will comment on those as soon as I have some time to post exact instructions on how to do this.

You can see this code here:

Thank you,
Kevin Liew Admin 13 years ago
Thanks Ian.
Eric 13 years ago
I have a problem when using the zip of the tutorial. There may be a syntax problem or something because I get this when I click on any link (in the simple demo and the styled one):
...introduction text...
'; break; case '#page2' : $page = 'Portfolio
... portfolio text...
'; break; case '#page3' : $page = 'About
... text...
'; break; case '#page4' : $page = 'Contact

On the web it works great., the demo doesn't. I'm using WAMP as a webserver (apache, php, mysql). Any idea what's wrong?
Kevin Liew Admin 13 years ago
ok, need to do some debugging here. try to access the php file directly to see if it generate any error. If t doesn't try to access each of the page with this:

javannele 13 years ago
the index page loads all content at once on the index page their is no page content separation
vidya 13 years ago
this is done using javascript but please send me the same webpage using ajax and php i mean using xmlhttp request..
Kevin Liew Admin 13 years ago
jquery ajax method is using xmlhttp request.
bri 13 years ago
Very nice tutorial. I'm new to AJAX. I was wondering is there any way of implementing this just using PHP get ids instead of hashes?
Kevin Liew Admin 13 years ago
It has to be hashes with javascript implementation. If you use GET, the browser will refresh and that isn't what you want in an AJAX driven website. :)
bri 13 years ago
Just for more clarification on my last post. Based on your example, is there a way I could display my url as an id like the one shown below instead of a hash? Thanks a lot.

Kevin Liew Admin 13 years ago
Please refer to below.
Petr 12 years ago
Hi, I've a same problem. Have you solved this problem yet ?
encoder 13 years ago
building an ajax site is building a fast as hell site. therefore the browser history engine becomes irrelevant since when your navigation is as fast as opening up a winamp and hitting the play button. you only need the homepage.

if your users use the back button that means you have a serious usability issue.

they are called url fragments and it's relatively easy to implement solving all the ajax shortcomings (or flash site for that matter).

browser need to have javascript enabled? well... screw those who don't have it. it's 2011 already.

advice for the usability issues:
have the menu (and the footer) always visible on the page, scroll only the content.
Kevin Liew Admin 13 years ago
Thanks for the update. 2 years since that article was published, so some of the points are no longer relevant in modern days. I strongly agreed with your comment, unfortunately sometimes when it comes to commercial work, that's something we have to take into consideration.
AndreNix 13 years ago
Running on Centos with php53 show error:

'; break; } echo $page; ?>
Kevin Liew Admin 13 years ago
that's weird, i haven't seen anyone have that issue.
PREM AMAN 13 years ago
I like your simple AJAX driven website. I want to know if there is a way to put the CSS in a separate file. Also, I am not able to figure our where the pages are saved - is it in the loader.php file or can it be in a separate pages folder. I am not a coder - please help
Kevin Liew Admin 13 years ago
hmm, that will be a harder for you then.

This is how you separate css code:

loader tells the script which page to display, in your case, you can do this:

//Get the page parameter from the url
switch($_GET['page']) {
case '#page1' : include 'page1.html';
case '#page2' : include 'page2.html';
case '#page3' : include 'page3.html';
case '#page4' : include 'page4.html';

just save the file in the same directory.
Xenet 13 years ago
Hey! Thanks for this great share!
One thing is disturbing me. When page1 is loaded and i click on page 2 -> Is it possible to fade the content slowly out before new content is loaded?

Want a nice fade from unloading till newloading?
somebody an idea? thanks in advance!!!!

Kevin Liew Admin 13 years ago
You can do this via line 27, $('#content').hide();, change it to $('#content').fadeOut('500')
Xenet 13 years ago
Thanks for your quick help but i used the optimized script from
Jonathon from the comments.

There is just one line like this (almost at the end): -> $('#content').hide();
When i replace it with:

it is not working. Do u have an idea how to fix this in jonathons script version ?!

thanks & regards!
Clancy Bird 13 years ago
Using ' ' in the function parameter list tells jQuery it's a string.. so it'll try and look up and match the parameter as a string, not an integer. You should use ' ' for words within the parameter, available; 'slow' 'medium' 'fast'. To use an integer representing the milliseconds of the fade only use the number, without the ' ' : )

// hide the content and show the progress bar
$( '#content' ).fadeOut( 2000 );
$( '#loading' ).show( );