One of the articles I updated during “May is Maintenance Month” was an article about dynamic content. The idea was a simple website where clicking a link would fade out the existing content and fade in new content that it fetched via AJAX. The old article didn’t encompass what I now consider to be best practices for this kind of thing. 1) Works fine with JavaScript disabled. 2) It is possible to “deep link” to specific content. 3) The browsers back button and forward button work as expected.
Links from Video:
very nice working thanks
Nice work, but the vid is a bit long….
I quite like the long videos.
Would you rather a short 5 minute video that brushes over the top? The great thing about Chris’ screencasts is that they are extremely in depth.
Long == “good”
Damn! Your the man.
You’re explaining things so downright understandable. Thanks a lot.
I have a question about the differences be this screencast and the one for WordPress. The wordpress one had a lot more code. What else needs to be accounted for in AJAXing a wordpress theme that this doesn’t cover besides working for all internal links?
What do you think the problem was with the “click” issue? It seemed that whenever you would initially load the page, the About link would not work before you used the Contact link.
You had thought that maybe you were already on the About page trying to load the About page, but you were really on the Home page, so there was a problem there.
Any idea why this would be happening? Thanks!
Hey Chris,
What about putting the content of the pages in a browser based cache? Like making an array and put the requested content in the array. Then first check if the array has already got the content. Otherwise do the Ajax request. This little one helps reducing the requeste.
That would be pretty sweet. I’ve never tried to do anything like that, but I guess the concept would basically be like preloading only for HTML content. I’m sure you could speed things up that way. If you know how and want to update the demo code to do it, that would be sweet.
Sure. I’ll give it a try. I know how to do this in native JS, but i’ll look into a jQuery solution ;) Just don’t expect anything before monday, because i’m pretty busy ^^
Correction: I already made it and it’s working properly. It even loads from cache when you do a page refresh, oddly.
The result: http://lievheid.nl/DynamicPage/
Awesome! Great work. Seems to work great for me.
I think the circumstance you use this would be when you are working on a page where you think that people switching back and forth between content is going to be highly likely.
That’s also weird it pulls from cache on page reload? Seems like your code only would fill the cache array as needed. I doubt those values would persist after a page refresh. Or are browsers smart enough to hold variable values like that?
Maybe this happens because the page refresh triggers the hashchange plugin? I don’t know. I would have to investigate the issue in question. However, if that’s the case, then it isn’t all that odd, because it’s nothing different from the back button.
Since you brought up the thought of preloading the HTML, you could naturally easily do something like:
$mainContent.hide();
var preloadSafe = $guts.html();
$("nav a").each(function() {
$guts.load(newHash + " #guts", function()
{
cache[newHash] = $guts.html();
$guts.html("");
}
);
});
$guts.html(preloadSafe);
$mainContent.show();
But i doubt this is preferable on sites with large amounts of content.
Sorry for my bugger:
newHash
must be
$(this).attr('href')
obviously.
That’s a swell idea as well, particularly for a site like the demo with just a few pages.
I’m addicted to your site Chris. I pretty much visit every day to learn something. Thank you very much.
Wow I am just new to js with a solid background in XHTML/CSS and this is such a clear example. Great work!
the back button in the demo on chrome doesn’t really work…but this is amazing as always
Haha funny screencast!
Really great screencast. I’ve been wondering what the deal with delegate() is for a while now, but I finally understand why it is more efficient since it only uses one event handler.
Well Other then what we were supposed to learn i had two thing stick out to me in the html. The <nav> tag and the tag are those a newer thing seems like in the past it’s always been ?
If I copy the link and go to the URL directly using the address bar, there is a problem.
Example:
If I put the address of –
https://css-tricks.com/examples/DynamicPage/about.php
and then navigate to the contact page, the URL shows up like this:
https://css-tricks.com/examples/DynamicPage/about.php#contact.php
Just a bug I thought you should be aware of.
Also, isn’t there a way to use the correct URL in the address bar instead of the hash? I could see a situation where a search engine would see the hash URL and the real URL as different pages with the exact same content.
Chris,
If the window.location.hash tag is changed to just window.location and if window.location.hash.substring(1); is changed to just window.location, the URL stays correct and everything seems to work correctly.
Is there something that I am missing? Is there a reason to use the hash tags in the URL? Just changing those two lines allows everything else to work but the URL looks the way it should.
I’ll have to try that out, but it’s my understanding that if you change the window.location value that the browser will reload the page with that location. I think it’s a security thing, like you could just change that value on page load to http://wellsfargo.com and pretend like your page is an official bank. Or am I wrong and you can change that without a refresh?
I just looked using firebug, running local (wamp), and with the demo files. Using the console, I still saw the Get requests and the URL stayed correct.
The animation of the page did stop working though.
To comment on the search engine part: Search engines don’t use JavaScript. The search enige would therefore not see any duplicate content. The point in leaving the hashlink is for users to have deep linking enabled and for search engines to have served proper content. I would however agree on the fact that if you want to refer to content with the permalink that uses this hash, you would mislead a search engine and the search engine would find no corresponding information, as where the user actually would.
The best solution to properly serve both users and search engines would be like how Chris did the site chris-mcgarry.com (See video screencast 84 for more info). Here he has all content preloaded, so search engines see all of it, and he hides what’s not being used by the user.
What I was referring to is if someone linked to test.html and someone else linked to #test.html that would be 2 separate links that are both valid. Through natural browsing, they pick up these different links. Both point to the same page and work. As far as the search engines that follow these links from different sites are concerned, they would be 2 different URLs with the exact same content.
When it comes right down to it though, I’m not sure how a search engine would interpret the hash. Will it think of it like an anchor link pointing to content that is part of a page or will it think of it as a different page. If it is content that is part of a page, it should think of it like content off of the index page. If it is a separate page, then you have the dup-content issue.
Or am I just wrong on all counts?
They wouldn’t have the same content. As i explained earlier, the search engine does not use JavaScript. Therefore if you go to #test.html, it wil actually load index.html or whatever your index page on that level is. This means we have two different links with both different content. I actually think a search engine would ignore a hash in a whole, because the default nature of a hash is to navigate to a certain area of a page, which a search engine wouldn’t need.
Chris I found a problem while using the example page: if you enter the page for the first time and you click the about link (for example) and then you click the back browser button you are not taken back to the home page…
Any solution?
Forcing the #home hash worked for me:
if(!window.location.hash)
{
window.location.replace(“#home.html”);
}
This works for me when I applied it to my wordpress site, but the content fades in before the wrapper resizes – creating overflowing for a split second.
Any way to fix it?
Nevermind! I fixed it by adding overflowing: hidden to the page wrap!
Yay. Solving problems feels so satisfying.
Thank you very much for the Video!
Thanks for the great video and demo!
In Safari, in contrast to IE and Firefox, it displays the containing white box of the contact page before the page length re-sizes. You end up getting the page length doubling up and down every time you visit the contact page. How could I fix the demo so that the contact page behaves like it should in Safari?
Thanks,
Sam
Great post Chris, Thank’s for updating!
I hope you like the additional feedback i give you for your “May maintenance month”, because i do want to help you out to get the fullest out of your
.Fantastic tutorial. As always, a great help to better understanding the jQuery world and seeing some creative ways to use it. Thanks
Great screencast again Chris, you describe everything so well and it’s allowing me to be more adventurous with my coding now I’m grasping it a lot better.
I was wondering how this would be incorporated with WordPress. How would you go about bringing the content of a subpage, with what I’ve done now I get site.com/page#/subpage.
Hey great tutorial I’ve learned a lot and have applied this technique in a wordpress template I am building.
I have a slight issue though – when I click on a button , it fades out fine, but when the new page fades in, it blinks twice and it is choppy.
The link is at http://www.cameronrafati.com/test/
Do you think you can give me a suggestion on how I can fix this issue?
Thank You!
Nvm! Zacks comment already helped! thanks
Nice tut, mate!
But what about javascript in pages, which i trying to load with ajax? For example, i have div with .jScrollPane() on it. And it doesn’t work, when i attempt to load it with ajax call. Any suggestions?
Unbind the function to that interesting div of yours, load the content and then when finished, bind it once again. That should fix the issue if the function does what i think it does and that is read out the height of the inner content of the div and if needed apply a scrollbar to it. You could also solve this by deleting the whole jScrollPane and in CSS adding a
#certaindiv { overflow:auto; }
where the browser will add a scrollbar if needed by default, using the css. This will also work if the content of the div changes, in realtime nonetheless.I have found another issue im having. The technique works great on FireFox but it is not workin w/ internet explorer? the site
is at http://www.cameronrafati.com/test –
Is their another component I need to add to have it work correctly on IE?
Thank you,
kenny
I took a look at your site and as you have it, you directly copied the JS from Chris. If this works in Firefox for you, i guess you modified your template to correspond to the JS, which is some interesting aproach which i will not get in to. As i see, you load a JS plugin before using the jquery library and before the DynamicPage JS. Now, i haven’t tested the JS in IE myself, so i can’t confirm anything there, but i do know that IE can be really bugging with JS. My guess is that the plugin somehow illegally, by IE standards, declared something, which let IE crash or stop running JavaScript. This would figure, because you loaded this plugin as the first JS. Moreover, Firefox, Chrome and Safari use their JS the right way and may actually not think of it as an illegal declaration.
What i found out the hard way is that when manipulating the HTML with JS, IE transforms it all to HTML4, uppercased HTML and attributes like href=”http://” are shortened to href=http://.
This could be problematic, because Chris selects the hash by means of the href attribute and if IE somehow lets jQuery interpret this as href=http://, while jQuery wants to select href=”http://”, then this actually is a bug in both jQuery and the script from Chris.
While the case where your earlier plugin in combination with IE messes things up sounds more likely to be right, i’d stick with that and try loading the page without that plugin and remake the functionality with jQuery, as you already loaded that horse of a framework.
wooo-hooo, great screencast! I’ll definitely try this for the project I’mon at the moment.
thx so much!
Thanks for this, I was doing something very similar to my website and this has really helped me. I only have one problem, I want to animate the background to a different color for each page but I can’t figure out how to do it.
Nice.
One thing I can’t figure out is how to handle Named Anchors…if possible.
I want the dynamic content a bit further down, and want to stay there when clicking. Now I end up at some mid point.
i tried to implement that one in a site and it worked, but when i put ithe page into a cms the browser doesn´t get the hashchanges. when i reload the page with the hash it works, but clicking on the links doesn´t have any effect….
what could be the problem?
Hi, is it possible to load content from the page itself (so all dynamic content to be loaded is on the same page already, just not visible until the menu item is clicked?)
Nice tutorial, however there’s 2 problems with this.
“Chris I found a problem while using the example page: if you enter the page for the first time and you click the about link (for example) and then you click the back browser button you are not taken back to the home page…”
There’s that.
And if someone with javascript on gives a link (with a hash) to a person with javascript turned of. The link wont work.
I’ve tried to come up with solutions for these problems but haven’t figured it out yet. Any ideas ?
I like this tutorial!
Thanks very much
This is awesome Chris! Now for a question:
Say your site has a lightbox effect for each image/video on the site by using a jQuery plugin –>
$("#guts a[rel^='prettyPhoto']").prettyPhoto({theme:'facebook'});
When new content is loaded dynamically by clicking on the navigation link, the lightbox effect doesn’t work because the content has been added afterwards. Which would indicate that we need jQuery’s live or delegate function…but I can’t figure it out. Any thoughts?Maybe the hashchange event triggers because you changed manually the url in the bar?
I’d try to copy paste the link with #about.html at the end in a new page, i’m pretty sure in that scenario the browser would load the main index.html page.
Great screencasts btw ;)
This player suck..better upload from youtube,cuz my internet is so fast,but your video uploading is sooooo slooooow..I wait about 5min until i watched 1min..damn..
Hey Richard did you figure this one out? I’m trying to add the jquery booklet plugin to Chris’s template, and I’m confused on how to get it to load. Not sure whether all js references should be on every .html, the index.html or the html that has the booklet. So far the best I can get is to load the page containing the booklet first instead of index.html. But the minute I navigate around the site and go back to the page containing the booklet I get a never ending “loading page” picture.
Is this dynamic loading site designed to load separate html’s that contain more than just text, images and simple forms?
Hi, great explanation for a beginner like me. Very easy to understand.
I’m currently looking to do my own website using this technique as I want music player (if pressed play) to not be interrupted if you browse another page (but still have bookmark function and work if no javascript etc)
HOWEVER, I’m browsing your demo page on a blackberry curve and the links do not work. If I click about, I get taken to the about page and the navigation bar shows on the about page, but the content remains home content. Is this inherent of this technique? Or could it be solvable. Mobile compatibilty is important to me.
Thanks,
David
Just 1 thing. This is called best practices yet it shows a bad practice. Namely where you place your scripts. The js libraries can be placed at the top but those scripts that react on a dom element must be placed at the bottom of the page. It ensures that those elements are loaded on the page especially when ajax is used.
great! i was hoping that the buttons/code on the index file wouldnt have to be repeated in each of the sub pages (about, contact). (having to modify the same nav on every single page instead of one master nav. i was hoping the index would pull all data from an external html file content into the main div.
so index has buttons/code/scripts, etc. and would call page1.html into the index page div. etc. (page1.html would only be a basic html page with just text (assuming i wouldnt need any of the head/meta info).
is this possible? i like the example, but seems to be duplicating alot of info on all pages…
Great tutorial…
Just wondering… if you had say a lightbox gallery on your 2nd page, how would you go about making it work correctly?
At the moment if there’s any javascript on the page that we want content from, the java does not work.
For the life of me I can’t seem to solve it! Any help greatly appreciated.
Indeed, this is a problem which I am having a similar issue with… entirely due to my lack of expertise with JS, I admit.
I’m implementing this as a main site navigation method (cuz I like the way it does what it does) and need to also utilize a lightbox effect and David DeSandro’s Isotope plugin (http://isotope.metafizzy.co/) for some components of the site. Can’t get it all to work in concert. I’m sure it’s something relatively simple but I’ve not figured it out yet.
So if anyone out there knows the key to solving stuff like this it would be greatly appreciated by many of us, I’m sure.
I have the same problem, there is already a solution
wow awesome… thanks :)
that i wanna ask to you, which better put # in href or without it??? because i’ve read some article about hashbang before, and many of them said to put #! (hashbang) in href.
i’m sorry for my bad english :)
I am implementing this on some navigation lower on the site. So the main nav just takes me to the pages that can begin the hashchange. However when I use the main nav to link to those pages no hash change takes place. I have tried adding the #nav id to the code but still no luck. I can expound if this doesn’t make sense. Any help would be appreciated.
Hi, Could you please kindly check out this url (http://www.altisrichmond.com/viewstop.html). Click on one of the floor in the nav on the left side. It loads the new content but the content on the page is messed up. I’m trying to get it to work but I think it’s conflicting with the other jQuery in the page. Any help would be appreciated. Thanks!
Hello,
Excellent page…But could anybody tell me how to make it work in Chrome?
It doesn’t do his job with Chrome!!
Hi Chris.
This is just what I need!
The only problem I’m having is that any links to pages that appear within the loaded page don’t load their respective pages dynamically. Or in other words load without the hash.
Anyone know how would I get around this?
This is very cool example. Just what I was looking for.
How do i change title of the tab when i click back and forward in browser , i mean when back and forward in browser in this video url is chaning but tab title is not.
Super great revamp: I had followed this before but it just seemed only for kicks… now it’s like, REAL !!! so cool. Would a 4th best practice be to have a loading gif? some of my “guts” are kinda big. ? ? ? net tuts had a “tut” but I can’t seem to smash both tuts together.
Anybody have a resource for a really simple switch out div with ajax and no hash or anything like that ? was thinking about creating a playlist of links and calling in new mediaelement.js players to create a hacky playlist player until they make one or I get a lot better with jQuery.
ps @ Colin – I tried to check out your problem… but the link is dead.
SHOP TALK SHOW !!!
Great tutorial, Chris!
I have 2 questions:
1. If you open demo, then go, for example, to “about” page and then go back with browser button then nothing happens cause start hash is empty. I think start hash should be defined like “home.php”.
2. If you reload page, for example, “about” then firstly loads “home” page and then changes to “home”. Is there a way to load directly “about” page by this link?
Thanks for your work!
I have a problem when trying to adapt this to a website using two navigations – one primary and one secondary.
http://darynjohnson.com/Medical%20Futures/the-awards.php
Any ideas?
This is probably one of the best screencasts I ever saw on CSS-tricks.com. Haven’t heard about hashchange event before.
So, quick question… How would you remove the “#” hash tag and turn the urls to display as:
https://css-tricks.com/examples/DynamicPage/index.php
https://css-tricks.com/examples/DynamicPage/about.php
https://css-tricks.com/examples/DynamicPage/contact.php
I know that you can do this with the .htaccess file, but is there a way in jQuery to do this?
How would you use this with a dynamic querystring ?id=12 instead of #id=12
thanks
Hi Chris. Picked up a thing or two from this video – thank you. Had no idea that window had a hashChange event.
One question though: you talk briefly about supporting non-JS browsers. However (and I haven’t tested this..) surely this doesn’t work with non-JS browsers? If I share a ‘deep-linked’ URL with a pal and a non-JS friend clicks the link – surely the only see the ‘base’ page without dynamically loaded content?
If this is true, I think it becomes a real issue if the page is shared via social media.
After 3 days of banging my head against it, I found ways to use this trick in combination with regular anchors within the same page, avoiding the fade flicker, and using css to automatically style multiple levels of navigation and current selections. Thanks for forcing me to learn JavaScript!
Hey can you explain how you got multiple layers of navigation with this function? I’m able to do 1 layer, but adding a sublayer that loads sub-content rather than main-content is eluding me. Many thx!
Hi,
how to remove hash(#) in addressbar
http://localhost:8000/ajax/#about.html
i am looking for like this
http://localhost:8000/ajax/about.html