Dynamic Page / Replacing Content

Avatar of Chris Coyier
Chris Coyier on (Updated on )

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

This article is an update to this old article, which had an ugly demo and a variety of techniques in it no longer probably considered good practices. This new demo is much cleaner, up to date, and fuller featured. Because the old article was a bit of a different scope, I’ll leave it alone, just refer to this one.
Update January 2013: There are better practices now, detailed here.

Let’s say you wanted to make a website where clicking buttons in the nav would dynamically load some content. Kind of like the organic tabs thing, only the content is loaded dynamically. Say something like this:

View Demo   Download Files

The HTML: It all works without JavaScript

There is no excuse for the navigation of a website to be completely broken without JavaScript enabled. So the best approach here is just to create these pages and the navigation as plain ol’ semantic HTML. You know, like it’s 2001.

The navigation links to the files that contain that content, and are fully formed functional pages on their own.

        <li><a href="index.php">Home</a></li>
        <li><a href="about.php">About</a></li>
        <li><a href="contact.php">Contact</a></li>


This isn’t really a tutorial about CSS, but if you want to peek at it, go for it. Shout out to Mike Rundle who shared the CSS for those buttons the other day on Twitter as I was working on this and I stole it.

jQuery JavaScript

The JavaScript is the fun part here! This is the plan in plain English:

  1. When a navigation button is clicked…
  2. Change the hash tag of the URL
  3. When the hash tag in the URL changes…
  4. Fade out the old content
  5. Load and fade in the new content
  6. Update the current navigation highlighting

So why bother with the “hash tag” changing stuff? Several reasons:

  • By using the hashchange event plugin by Ben Alman, we can enable the browsers back/forward button. Super modern browsers support the hashchange event by themselves, this plugin enables support for it for older browsers.
  • We can look for the hash when the page loads and load the appropriate page (i.e. “deep linking”)


We’ll be using the jQuery library, the onhashchange plugin, and then loading our own script last.

<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js'></script>
<script type='text/javascript' src='js/jquery.ba-hashchange.min.js'></script>
<script type='text/javascript' src='js/dynamicpage.js'></script>

Code Dump

$(function() {

    var newHash      = "",
        $mainContent = $("#main-content"),
        $pageWrap    = $("#page-wrap"),
        baseHeight   = 0,
    baseHeight = $pageWrap.height() - $mainContent.height();
    $("nav").delegate("a", "click", function() {
        window.location.hash = $(this).attr("href");
        return false;
    $(window).bind('hashchange', function(){
        newHash = window.location.hash.substring(1);
        if (newHash) {
                .fadeOut(200, function() {
                    $mainContent.hide().load(newHash + " #guts", function() {
                        $mainContent.fadeIn(200, function() {
                                height: baseHeight + $mainContent.height() + "px"
                        $("nav a").removeClass("current");
                        $("nav a[href='"+newHash+"']").addClass("current");


Not much to it really. It’s only 41 lines with some blanks in there for readability. This even includes adjusting the height of the whole wrapper to adjust for the new content.

View Demo   Download Files