A simple AJAX website with jQuery

Demo Download


This time we are going to create a simple AJAX website with jQuery and the right amount of PHP & CSS. It is going to have a few pages loaded by AJAX from the PHP back-end, and a complete support of the browser history - a real pain for any AJAX or Flash site .

So get the demo files and lets start rollin'.


First, we create the XHTML backbone of the site.


<div id="rounded">

<img src="img/top_bg.gif" /><!-- image with rounded left and right top corners -->
<div id="main" class="container"><!-- our main container element -->

<h1>A simple AJAX driven jQuery website</h1> <!-- titles -->
<h2>Because simpler is better</h2>

<ul id="navigation"> <!-- the navigation menu -->
<li><a href="#page1">Page 1</a></li> <!-- a few navigation buttons -->
<li><a href="#page2">Page 2</a></li>
<li><a href="#page3">Page 3</a></li>
<li><a href="#page4">Page 4</a></li>
<li><img id="loading" src="img/ajax_load.gif" alt="loading" /></li> <!-- rotating gif - hidden by default -->

<div class="clear"></div> <!-- the above links are floated - we have to use the clearfix hack -->

<div id="pageContent"> <!-- this is where our AJAX-ed content goes -->
Hello, this is the default content


<div class="clear"></div> <!-- clearing just in case -->

<img src="img/bottom_bg.gif" /> <!-- the bottom two rounded corners of the page -->


This code is positioned in the body part of our demo.html file. Its main purpose is to serve as a front-end to the php back-end, with jQuery handling all the communication in between.

Note the addresses of the navigation links - #page and a page number. This part, called a hash, is included in the current URL without a page refresh, creating an entry in the browser's history. By monitoring this hash with javascript, we can change the loaded page by AJAX and provide a seamless browsing experience.



Lets take a look at our style sheet.


small,form,input,ul,li,ol,label{    /* resetting our page elements */
    font-family:Arial, Helvetica, sans-serif;

body{   /* styling the body */

.clear{ /* the clearfix hack */

a, a:visited {  /* styling the links */

a:hover{    /* the hover effect */

#rounded{   /* the outermost div element */
    margin:20px auto;   /*center it on the page*/

.container{ /* this one contains our navigation, titles, and fetched content */
    padding:10px 20px 20px 20px;

h1{ /* the heading */
    font-family:"Trebuchet MS",Arial, Helvetica, sans-serif;

h2{ /* the subheading */


ul{ /* the unordered list used in the navigation */
    margin:30px 0px;

li{ /* we float the li-s, which contain our navigation links - we later apply clearfix */

li a,li a:visited{  /* the navigation links */
    padding:5px 10px;

    -moz-border-radius:5px; /* rounding them */
    -khtml-border-radius: 5px;
    -webkit-border-radius: 5px;


li a:hover{

#pageContent{   /* the container that holds our AJAX loaded content */

    border:1px dashed #cccccc;

    -moz-border-radius: 5px;    /* rounding the element */
    -khtml-border-radius: 5px;
    -webkit-border-radius: 5px;
    border-radius: 5px;

#loading{   /* hiding the rotating gif graphic by default */

An important reminder would be to note that rounding corners with CSS is only supported in the latest versions of Firefox, Safari and Chrome.

The jQuery source

To complement the front-end, here is the script that drives the site.


$(document).ready(function(){ //executed after the page has loaded

    checkURL(); //check if the URL has a reference to a page and load it

    $('ul li a').click(function (e){    //traverse through all our navigation links..

            checkURL(this.hash);    //.. and assign them a new onclick event, using their own hash as a parameter (#page1 for example)


    setInterval("checkURL()",250);  //check for a change in the URL every 250 ms to detect if the history buttons have been used


var lasturl=""; //here we store the current URL hash

function checkURL(hash)
    if(!hash) hash=window.location.hash;    //if no parameter is provided, use the hash value from the current address

    if(hash != lasturl) // if the hash value has changed
        lasturl=hash;   //update the current hash
        loadPage(hash); // and load the new page

function loadPage(url)  //the function that loads pages via AJAX
    url=url.replace('#page','');    //strip the #page part of the hash and leave only the page number

    $('#loading').css('visibility','visible');  //show the rotating gif animation

    $.ajax({    //create an ajax request to load_page.php
        type: "POST",
        url: "load_page.php",
        data: 'page='+url,  //with the page number as a parameter
        dataType: "html",   //expect html to be returned
        success: function(msg){

            if(parseInt(msg)!=0)    //if no errors
                $('#pageContent').html(msg);    //load the returned html into pageContet
                $('#loading').css('visibility','hidden');   //and hide the rotating gif



Note how, on line 3, we call the checkURL() function as soon as the page finishes loading - this way we insure that, if a link to an inner page on the site has been shared and a new visitor visits it, the site will fetch the required page and show it when the page is loaded.

As you can see on line 11, we setup an interval for checkURL() to check the browser's address 4 times a second in order to detect any possible changes arising from the use of the back/forward buttons.

Now lets take a look at the back-end.


The PHP back-end is just a few lines of code and is the place to start, if you want to customize this example.


if(!$_POST['page']) die("0");

$page = (int)$_POST['page'];

echo file_get_contents('pages/page_'.$page.'.html');

else echo 'There is no such page!';

It basically checks whether the variable $POST['page'] is set, and if it is, checks whether the respective page.html file exists, and outputs it back to jQuery.

You can improve upon this by fetching data from a database, by using sessions, or displaying a folder of images - anything you might have on your mind.


Today we created a simple, customization-ready, AJAX enabled web site. Feel free to use the code and the techniques that were demonstrated in any of your projects.

Bootstrap Studio

The revolutionary web design tool for creating responsive websites and apps.

Learn more

Related Articles

This is a really interesting one i loved reading it. Yeah it is a simple one.

Nice tutorial.. I m thinking to add ajax for viewing post in wordpress.

same here :)


Awesome...thanks for this tut...!

its a little messy in ie8

Martin Angelov

Fixed. Seem to have uploaded an older version. Enjoy.

Hmmm, nicely done but I have an question.

What about changing: load_file.php >>> insted load HTML load PHP

6.echo file_getcontents('pages/page'.$page.'.html');

When i change
[...]_'.$page.'.html')) [...]

firefox just ignore and leave blank space as He just coudln't use php file.

Thanks for help


include ('pages/page_'.$page.'.php'); insted 6.echo file_getcontents(’pages/page’.$page.’.html’);

worked, so nvm.

Thanks for great tutorial

@selem: nice... got some trouble while calling php files instead of html... thanks for this... hehehehe...
and for the author of this tut... keep it up... very useful stuff,,

I really like this affect, great article.

One question though. I know you've allowed for the history to work when you click the back button but when I click a few pages then click back until I get to the webpage that doesn't have a #anchor in the URL (the initial page) then it just shows the animation spinning.

Is this an issue? And if so, does anyone know how to correct it?

Martin Angelov

@amnesia7 -
Thanks for noticing. I updated the demo and the download files. You can check it out.

Kartlos Tchavelachvili

Thanks for this cool simple demonstration, it is very useful

Montana Flynn

Good tutorial, but I would make sure to have it work with javascript disabled. The method I use is to .hide the elements with jQuery instead of CSS, it has a slight flickr, but its not too bad.


Nice simple one page website created using the jquery slider techniques.

Absolutely superb!! I might bring this into the IM world for modern sales pages.



awesome tuts... i like it... ( luv u martins.) no homo !

Hi all , thanks for this tutorial very nice, but i don't understand how to make this work with php file with sql, echo ""; etc
If someone can explain, i try everything and nothing appears
Thanks :)

Awesome tutorial, used it to create an archives page for my blog, thanks! :D

what do I have to modify or add, if I want to use additional anchors within a ajax loaded site? e.g. in page_1.html I want to add a anchor.

Thank you. An another good tuto.

I noticed you are not using return false on any of your javascript and your code does not shoot the user back up to the top.

How are you accomplishing this? I always have to do a return false; to avoid this.

Loved the concept. Thnx for sharing the idea :)

Hi, how can we add php search, i did a page with a link request looking like. #page5?search=my search term

But it's doesn't work

I changed the load_page.php to

echo file_getcontents('pages/page'.$page.'.php');

echo file_getcontents('pages/page'.$page.'.html');

It's working for php normal link but how to do a search query?

Hey ! mine is not working. i tried to do simpler, something like just.. about page, services page and its not working. the jquery file
is like this:

function loadPage(url) //the function that loads pages via AJAX

$('#loading').css('visibility','visible');  //show the rotating gif animation

$.ajax({    //create an ajax request to load_page.php
    type: "POST",
    url: "load_page.php",
    data: 'page='+url,  //with the page number as a parameter
    dataType: "html",   //expect html to be returned
    success: function(msg){

        if(parseInt(msg)!=0)    //if no errors
            $('#pageContent').html(msg);    //load the returned html into pageContet
            $('#loading').css('visibility','hidden');   //and hide the rotating gif


Hey! Thanks for sharing this script. I have tried it, and it works perfectly in firefox,safari and chrome. But, in IE version 7 and lower, the anchor tags aren't treated as history, which means that the backbutton will send you to the previous website and not the previous anchor within the site.

Do you have the same problem, or is it my IE versions that are messing with me?

This is really cool. I completed the tutorial. everything worked fine except loading the pages. any help will be appreciated

Heshan Peiris

Cool article

you guys have done a great job at showing off your skills? I long something new every day.
I wish jounld buying a show long list of how it is all done .
Once at ;


I have also problem loading the pages for the demo. Any help would be appreciated :)

Awesome demo and tut. Is there any way of doing exactly the same thing in classic ASP (not .NET) instead of PHP? Can you point me in the right direction? Any assistance would be appreciated.

Patrick H.

Great tutorial! Is it possible to replace #page1 link for /page1 link? I replaced hash for slash in the script, but it doesn't work.


I'm trying to use your siple website. It work fine with content, but when i place a adsense code on page1 for example:

  • on firefox it stops working and everything goes blank...
  • on IE8 it works but doesn´t display the ad...

is there any to correct it and make it work with google adsense?

thanks a lot


great script only onee problem for me....is there anyway to stop the #page appearing as the at the top of the browser

Great tutorial
very easy to understand it........
Thanks for the great tut again... keep it up

Hi, I have a question:

I want to put one of the pages loaded by default. For example page2.html

How do I do?


Eugenio Burress

This is a wonderful article, im lucky I recently found this. Ill be back down the track to check out other posts that you have on your blog.

Nice tut, but too many mistakes...

that's very nice, i wonder can i find the sample tutorial with asp.net?


The history doesn't work for me in IE7 and earlier. I think it has to do with the checkURL() function - for some reason IE7 (and earlier) doesn't seem to detect that the data is new after the new html files are loaded. Like IE7 isn't checking for an updated XMLHttpRequest or something.

It works in IE8 and other browsers.

Anyone else experiencing this?

Hi, if you place an internal / external javascript in the head of one of the ajax pages will it be executed when the li is clicked?

Great tutorial. Most tutorials get into way to many unimportant details which leaves the reader confused. This is a great way to build a foundation for using jquery to perform Ajax since I’m a jquery newb. Thanks!

HD radio

Nice and easy to understand! Thanks

template in Vietnam

very nice ! i love it so much, thanks a lot

Great tutorial. Good usage of the border-radius as this is now standard on all modern browsers. Can be used to create a good effect without having to include JQuery UI and its overhead.


For SEO purposes, I would like to change the page1, page2, ....etc to something more useful such as the actual page-name.html but not exactly sure how you would do that? Any suggestion from anyone to give me a starting point is very appreciated as I'm intermediate in both PHP and Javascript. Thanks!


Also wondering if there's a way to change the Title of the pages loading in that div to effect the main title (for example your demo page right now says A simple AJAX website with jQuery) and I want to change that according to each page.

Greg Formager

I have the same question - I would like to use different names for the pages instead of "page_1", "page_2", etc.

I can't figure out how to make this work..

Arjun S Kumar

I've been using the AJAX part to be implemented on my personal site, and when I include the Prototype the AJAX part doesnt works! I've been using prototype for using lighbox gallery plugin to use in my image gallery section. Any suggestions or fixes on this issue?

Very nice tutorial! Thank you!

I have one question, how to get one of the buttons to get active status to style with css?

million thanks, martin.. this really helped me.. i tried many other, but this one worked perfectly.

Hey Martin, I was just wondering how I could pass a simple GET parameter to one of these pages. Any help would be great.

Simple and neat. Martin, you are amazing, it's great that you add the files for every tutorial. Thank you!

Figured it out replace the function loadPage(url) with this: (Be sure to change out your $(".extLink").fancybox({ with what your fancybox link type is...)

function loadPage(url)


        type: "POST",
        url: "load_page.php",
        data: 'page='+url,
        dataType: "html",
        success: function(msg){
                    function() { 
                        .fadeIn('slow', function(){ 
                                    'width' : '75%',
                                    'height' : '100%',
                                    'autoScale' : false,
                                    'transitionIn' : 'elastic',
                                    'transitionOut' : 'fade',
                                    'type' : 'iframe'
                        }, 600);



The code works perfectly, however when I use another anchor for example to send people back to the top of the page, it treats it as an ajax query and it gives me the "This page does not exist" error. Is there a way to fix this?


hi, got a question about using jquery library

when i change loaded script

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script&gt;

into new version f.e
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script&gt;

its collapsing, other page #page1 #page2 etc. is loading, but can't do it right. Any ideas, how to load new jquery library?

Could someone please tell me is this method SEO friendly? Very nice tutorial btw.

tank u for usefull tutorial...
how can i change name of fies ?!
i want use #about , #contact Instead of #page_1 ...

did anyone resolve this?

any idea much appreciated!!

Great tutorial !

Changing the kind of pages to load in is also very simple. ( You can choose to load simple html pages, or php pages, as you wish )

But what about loading php pages with GET parameters ? It would be one thing to extract the correct filename out of the url, no problem with that as you can get the index of the ".php" string part ... and everything after that index can be seen as 'the parameters string part'

that would mean :

for example: products.php?category=fruits

  • Get the indexes of the ".php" string-part ( => 8-to-12 )
  • You now have the correct page beïng: from index 0 to 12 => "products.php"
  • now strip the complete string with the correct page string => "?category=fruits"
  • you check if the page exists with the correct page string => "products.php"
  • and you load in the complete url you have now : "products.php?category=fruits"

If you have all this data, you should be able to make it work for PHP pages with GET parameters attatched.

Or am I wrong ? - Any notes on this ?


is there any way to change the page names so it says #contact etc instead of #page_1....

any suggestions welcome!

thanks in advance

Great tutorial. thanks a lot.

thanks for the tutorial, I want to learn about ajax. :))

Have you seen AjaxGetContent plugin? It allows to transform a standard, traditional website into a fully AJAX-based one. It maintains back/forward browser buttons functionality and content visibility for search engines like Google.

Here is the link to the documentation:

Sample sites with plugin integrated (mainly in Polish):
http://www.implico.pl/lang-en/ (our homepage)
http://www.ptchprie.pl/ (Polish Plastic and Aesthetic Surgeons Society)
http://www.finestra.pl/ (PVC windows manufacturer)
http://www.sportolimp.pl/ (wholesaler of sport goods)

Enjoy reading & integration!

Amazing tutorial, thank you Martin.

In order to change the url name from page numbers to desired name.

in function loadPage(url)

function loadPage(url)

var datastring=url.replace('#','');    //strip the # and leave only the page name

$('#loading').css('visibility','visible');  //show the rotating gif animation

$.ajax({    //create an ajax request to load_page.php
    type: "POST",
    url: "load_file.php",
    data: 'datastring='+datastring,   //add datastring here
    dataType: "html",   //expect html to be returned
    async: false,
    success: function(msg){

        if(parseInt(msg)!=0)    //if no errors
            $('#content').html(msg);    //load the returned html into pageContet
            $('#loading').css('visibility','hidden');   //and hide the rotating gif


in load_page.php

$url = $_REQUEST['datastring'];
echo $url;

echo file_get_contents(''.$url.'.html');

else echo 'There is no such page!';


Here i have saved the html files that i have to access is stored where load_page.php is stored.

Kind Regards

You can also use the link with Ahmed's solution, to hide index.php page.-

If you want to load an inline page(iframe), just paste the code in a blank text page and then load, it will display the iframe.

I want to display the result of the search engine of my web site in the middle.
I can do it with this code since I have always an error wich is : "undefined index" Thanks.

Thank you! thank you! thank you! ...a thousand times! This is just what I was looking for this morning and got it working pronto!


An alternative : you can have it without need of php code or heavy javascript code.

Consider using the jquery.xtarget plugin and replace your links with it :

<li><a href="page1.html" target="#pageContent">Page 1</a></li> <!-- a few navigation buttons -->
<li><a href="page2.html" target="#pageContent">Page 2</a></li>
<li><a href="page3.html" target="#pageContent">Page 3</a></li>
<li><a href="page4.html" target="#pageContent">Page 4</a></li>

And put the content of each tab into each page*.html.

More info here : https://github.com/bapplistudio/jquery.xtarget

Mutebi Roy

Waiting for an Advanced Ajax Website Tutorial. Thanks guys

I used your files and everything is ok. The only problem is that when I load a page that has some kind of jQuery banners, they stop.
I'm using boostrap (a css framework) that has some jquery plugin: carrousel, etc...All the javascript at internal pages stoped
Did someone find this too?


Very nice tutorial, I love it. thanks.

Mark Morris

This is a very helpfully simple job.Thanks!
One issue I have, though, is that it doesn't seem to work with later jQuery scripts.
If I include 1.3.2 (as used here), that in turn stops other items working.
Any solution?

I have a similar AJAX structure to your code, but using pure JavaScript instead of jQuery. I have noticed several things you have done differently, and was wondering if there was any perforpance benefit or such

-Why are the "checkURL" and "loadPage" functions seperate?
-Why have the extra step of "load_file.php"? You can do everything the "load_file.php" file does from the "loadPage" function with JS.

Myfi Myfitto

const LOADDIR = "/var/www/private/html/"; // Your directory with PHP/HTML files included.

if (isset($_GET[&quot;page&quot;])) include(LOADDIR . $_GET[&quot;page&quot;] . &quot;.php&quot;);
else die(&quot;No page to display.&quot;);


This is even better solution (it will execute PHP code inside HTML - use include() instead of file_get_contents() etc.)!