Hashbang and pushState

A while ago, Google made a suggestion for crawling websites that used AJAX for navigation. Soon after, Google implemented the idea in their search engine. Few paid attention to this until last September, when Twitter started using the technique. Then, last week, Gizmodo adopted the technique, and the internets promptly exploded.

The technique, known as "hashbang," relies on URLs of the form http://example.com/#!path/to/content. Opinions on hashbangs are varied, in that some people think it's bad while others think it is terrible, no good, or very bad. There is widespread agreement this isn't how the web is supposed to work, and strong evidence that it really doesn't work at all, beyond a very narrow definition of "works." Simon Willison has collected several articles under a tag of "hashbanghell".

Without rehashing all of that, let's simply agree that hashbangs are an affront to all that is good and decent on the web and those pushing this technique are, as Tim Bray put it, "beating the Web to a bloody pulp with a sharp-edged hashbang." With that agreement, let's move on to learning something from this experience, something more interesting than "hashbangs are bad."

Why do bad things happen to good URLs?

If hashbangs are so terrible, why are people using them? Mike Davies says "Out of all the reasons, the strongest one is 'Because it’s cool'." Tim Bray doesn't find it cool, dismissing it as "dynamic AJAXy magic". Jeremy Keith doesn't seem to even recognize that others might find hashbangs cool, saying "I’m so surprised that any front-end engineer would knowingly choose to swap out a solid declarative foundation like HTML."

Words like "cool" or "magic" are dismissive of the benefits of hashbangs. This may be a rhetorical device from the "considered harmful" school of blog posts, in an attempt to shame the web away from every using hashbangs again. Or maybe people really don't recognize hashbangs as doing anything remotely good. Either way, we should look the real benefits of hashbangs: for most people, hashbangs improve usability.

for most people, hashbangs improve usability

Hashbangs reduce two of the most fundamental usability issues with web interfaces: responsiveness and context. The web is made of links, and every link we click causes a full page refresh. We have to wait for that page to refresh (the responsiveness problem) and while we wait, we have a visual gap between the previous page and the next page (the context problem). Interfaces in our native applications don't generally have these problems. They can smoothly and quickly transition between contexts in ways that don't require users to re-orient themselves at all. As web professionals, we're all experienced enough that we've learned to ignore these problems, but they're still usability issues. Hashbangs greatly reduce these negative aspects of page reloads by removing page reloads. For most people, that's a usability improvement.

For most people

The fundamental problem with hashbangs is simply that the web was never intended to be usable by most people. Pretty much every part of the web is built to be fault-tolerant, so if something doesn't work for even a small minority of users, the rest of the web does work, and the general experience is still usable. Hashbangs improve usability for most people, but completely break usability for others. See the articles above for a description of specifically how hashbangs break the web. The question we should be asking, once we've recognized that hashbangs improve usability for most people, is how can we gain those usability improvements without breaking the web?

Twitter comes close to doing hashbangs well. If you're using a system that doesn't support hashbangs, you'll generally never see them on Twitter. You'll instead get a fully-functional Twitter experience with the old, non-hashbang URLs. Gizmodo does this part completely wrong, completely disabling the old URLs. I wonder if Gizmodo might have gotten away using hashbangs had they employed progressive enhancement as well as Twitter did. But even though Twitter works well for an individual non-hashbang user, that's not good enough because the web is a social environment, people pass URLs around. If my browser doesn't work with hashbangs, and you send me a hashbang URL, it won't work for me. This is especially problematic for Twitter, as passing around URLs is a large part of what Twitter does.

So how do we solve this problem? It's a complicated problem, and I couldn't think of a good solution. So I'm happy HTML5 has already solved it for us. <a href="http://badassjs.com/post/840846392/location-hash-is-dead-long-live-html5-pushstate">window.history.pushState()</a> allows sites to change the URL in a browser without a page refresh. Because pushState is using standard URLs, this gives us all the usability improvement of hashbangs, with none of the breakage. Everyone wins.

So yes, hashbangs are evil, but they're evil in the service of usability, and usability is good. Rather than tossing out that usability improvement, we should be pushing sites to improve usability the right way, with pushState.

Usability

Read This Next