Here is our take on news, art, ideas, technology, the web, and things we like - join the discussion and don't forget to subscribe to the RSS feed.

   Jamie Appleseed

HTML5: Changing the browser-URL without refreshing page

An often overlooked feature of HTML5 is the new “onpopstate” event.

This new feature offers you a way to change the URL displayed in the browser* through javascript without reloading the page. It will also create a back-button event and you even have a state object you can interact with.

This means you won’t have to use the hash-hack anymore if you want add state to your AJAX-application, and search engines will be able to index your pages too.

So how does it work? Well, it’s fairly simple. In Chrome you write:

window.history.pushState(“object or string”, “Title”, “/new-url”);

Executing this line of code will change the URL to my-domain.com/new-url (3rd option). The “Title” string (2nd option) is intended to describe the new state, and will not change the title of the document as one might otherwise expect. The W3 documentation states:

“Titles associated with session history entries need not have any relation with the current title of the Document. The title of a session history entry is intended to explain the state of the document at that point, so that the user can navigate the document’s history.”

So if you want the document’s title to change to match the title of the history entry, you’ll need to write a hook for that (hint: just tie a function to the onpopstate event). Finally, “object or string” (1st option) is a way to pass an object to the state which you can then use to manipulate the page.

You can programmatically invoke the back-function by running:

window.history.back();

And you can of course go forward too:

window.history.forward();

Or even go to a specific history state:

window.history.go(2);

The object you pass as the first option to the pushState function will stay with each state, so if you go back in the history, you’ll get the object for that state. If you need to manipulate a state (instead of creating a new one) you can use:

window.history.replaceState(“object or string”, “Title”, “/another-new-url”);

Note that while this will change the URL of the page, it will not allow the user to click the back-button to go back to the previous state because you’re replacing the current state, not adding a new one. So, this is the correct behaviour.

Personally, I think the URL should be the first parameter and then the two other options should be optional. Regardless, this feature will certainly come in handy when working with AJAX- and Flash-applications that need state (read: bookmarkable pages and back-button support). Anyone looking to make their Flash- or AJAX-application indexable by search engines so they will get better raking in Google and the likes, should also have a look at this new feature.

The most prominent implementation of this HTML5-feature that I’ve seen is in the new Flickr layout. Here’s an example page (remember to enable the new layout if you haven’t already). Now, if you’re using the latest version of Chrome or Safari and click one of the sets, e.g. “Strobist”, it will slide open and the URL will change but you’ll notice that the page doesn’t reload.

It’s worth noting that Flickr uses replaceState instead of pushState – in other words, they don’t add a back-button event. I’m guessing they feel that switching back and forth between opened/closed sets is too small a change for a back-button event (I’d certainly agree with them on that decision), so instead they just replace the URL so if you copy/paste the link to a friend, they’ll see the exact same page that you did.

Another interesting thing is how Flickr still use the old hash-hack as a fallback if you’re running on browsers that don’t support this new HTML5-feature. I predict/hope that a lot of the plugins that help you easily implement the hash-hack will bake this into their core so people with new browsers can start reaping the benefits.

The latest versions of Chrome and Safari already have support for “onpopstate” and Firefox 4 will have support for it as well. Unfortunately, it seems like IE9 won’t be supporting this feature if we are to believe this Wikipedia article (“Trident” is IE’s layout engine).

Check out the W3 specification for more info.

* For security reasons, you can only change the path of the URL, not the domain itself. So you can change anything in the URL after my-domain.com/[change-the-stuff-here.html].

  1. Since window is the global “context” object, everything that is a property of window is accessible without spelling ‘window.’ out in browser JavaScript. So it makes no difference whether you write ‘history’ or ‘window.history’, both will access ‘window.history’ (unless you have a local variable history shadowing the global, of course).

    Comment by moeffju

  2. Great writeup for a long overdue feature. I hope that IE9 might still include it after all, but anyway, off to try it out.

    Comment by Ilia

  3. Looks like this feature was removed from the current spec, however.

    Comment by wdh

  4. Ah hell, I don’t know yet, but a quick search didn’t find it. Was definitely not a thorough search, however.

    Comment by wdh

  5. There’s no such thing as accessor for window properties. In JS window is the global object. All global variables are window properties (alert() === window.alert()).

    Comment by kl

  6. This is neat, good it’s supported in HTML5. It was pain to handle these ourselves.

    Sad to hear about IE, not sure why M$ doesn’t always comply with standards?

    Thanks

    -abdul

    Comment by Abdul Qabiz

  7. Ahoy, thanks for noticing this. I’m the one at Flickr who implemented this stuff.

    Deciding when to use pushState and when to use replaceState can get a little subjective. We’re basically making our best guess at which interactions a user would expect a back button to undo. So, we use pushState for opening and closing the lightbox and navigating to another photo in the lightbox. But we use replaceState for paginating comments and changing contexts (as you mentioned for sets).

    Comment by Trevor

  8. Pingback: TempusFactor » Blog Archive » links for 2010-07-21

  9. Thanks for using my photo in this blog post!

    Comment by Aaron Nace

  10. Really informative, thanks!
    I saw that Flickr behavior and was wondering how it was working… I even thought it could be a Chrome’s bug!

    This here will change the face of the web. And it might create bad ideas, too. Like client side Javascript URL rewriting (looks dumb but I’m sure some folks/clients will want that)…

    Comment by Quentin

  11. Couldn’t this be abused by filling up the history with spam sites – sort of like how redirect can seem to lock you into a site by refusing to go back in history?

    Comment by Wouter Van Hemel

  12. I now use it on my company website : http://studio87.fr with a # fallback for browsers that don’t support it

    Thanks for that great article !

    Comment by riper

  13. Oh good, now we’re going to have annoying things like this used to be

    http://www.javascriptkit.com/script/cutindex19.shtml

    Comment by 0x1337c0de

  14. Thanks for your clean explanation!

    Comment by Marçal Juan

  15. Thanks for the pointers to the APIs. I’ve started a project to port the API to browsers that don’t support it:

    http://github.com/fortes/history.js

    Patches welcome! :)

    Comment by fortes

  16. @moeffju + kl
    Thanks, I’ve removed the inaccurate note.

    @Trevor
    Great job on implementing this! I think you hit just the right balance in deciding when to use pushState and when to use replaceState.

    @Aaron Nace
    Thank *you* for some brilliant photography!

    @Quentin + Wouter Van Hemel + 0x1337c0de
    Like so many other javascript features, this can be abused. However, I don’t think we can limit useful innovation because some may abuse it. While not having the “Back button” work is annoying, it’s not a major security threat or anything.

    @riper
    Well done. This is exactly the kind of use we’ll be seeing more of in the next months. Use pushState for browsers that support it and having the good ‘ol hash tag hack for IE.

    @fortes
    Interesting project – good luck with it!

    Comment by Jamie Appleseed

  17. Hey guys, for a backwards compatibility History.js – https://github.com/balupton/History.js – gracefully degrades the HTML5 History/State API for HTML4 browsers while keeping support for data and titles as well as replaceState functionality. It also fixes a few browser incompatibilities with the API. Supports jQuery, MooTools and Prototype out of the box too :-)

    Comment by Benjamin Lupton

  18. Pingback: 180+ HTML5 Tutorials and a Round-Up of HTML5 Round-Ups - WebsitesMadeRight.com

  19. Pingback: 180+ HTML5 Tutorials and a Round-Up of Round-Ups - WebsitesMadeRight.com

  20. Pingback: 270+ HTML5 Tutorials and a Round-Up of Round-Ups - WebsitesMadeRight.com

  21. Useful resource that i was searching for it for 1 week :5 Grat work bro ! Thanks

    Comment by Bari Rafik

  22. Pingback: Cool feature of HTML5 | GUYA.NET

  23. Pingback: Redes sociales y la adopción de los nuevos estandares. | Luis Carlos Cárdenas

  24. Pingback: Cool feature of HTML5 « ARMATE THE TECHMATE

  25. StackOverflow uses this new feature (it’s been implemented recently). I was doleful to implement it in my site, but now with large sites like SO using it, I’m completely happy.

    Great article. Thanks.

    Comment by Saeed Neamati

  26. What a nice article!
    Thank you very much. :D
    It’s so useful for me.

    Comment by 월풍

  27. Here is an example demo to implement FACEBOOK like MENU navigation without refreshing the page but changing the url using HTML5 and get the content using AJAX
    http://tinywall.info/demos/html5-history-api/menu1.php

    Comment by Arun David

  28. I will implement im my site in the future

    http://www.equipebeta.com.br

    thanks for this script

    Comment by Renato Cassino

  29. I am writing a “web app” for smartphones (iOS and Android) where I use JavaScript to create a finite state machine to deliver my app functionality. I also have the need to navigate to other HTML pages within my app. When navigation transitions back to the home page where the FSM resides, I need that page to be “as it were” without a page reload. Currently, the “webview” support in the smartphones causes a page reload. I definitely will explore this HTML5 pushState capability as a solution for my requirement. Thanks.

    Comment by David

  30. yay. found this by searching for “html5 url” on google.
    just wanted to know how to do it for a private local hosted manga reader project.

    Comment by GottZ

  31. thanks for this script
    i implement it in my site

    http://astaza.com/

    but there are better way to use ajax with jquery
    http://benalman.com/projects/jquery-bbq-plugin/

    thank you

    Comment by العاب

  32. Pingback: How can I change the page URL without refreshing the page? | Easy jQuery | Free Popular Tips Tricks Plugins API Javascript and Themes

  33. Thank u, i was finding this way, by searchng this i have find out the gleam theme for wordpress used at this blog scienceinhand.com

    Comment by Irfan korai

  34. Here is an example demo to implement FACEBOOK like MENU navigation without refreshing the page but changing the url using HTML5 and get the content using AJAX

    Comment by Imran Korai

  35. AMAZING! Url change without a postback, I never thought it would be possible.

    Comment by guideX

  36. Hi,
    I using this window.pushstate to change my browser URL and i am doing it @ the success of ajax request. Will it cause the page to reload, coz its happening like that now :(

    Comment by Arjun

  37. When I originally commented I clicked the Notify me when new comments are added checkbox and now every time a comment is added I get 4 emails using the same comment. Is there any way you may take away me from that service? Thanks! bebbeaedkeeg

    Comment by Johnk340

Leave a Reply

Your email address will not be published. Required fields are marked *