javascript:void(0) must die
Pretty much two weeks ago I dropped my notes from FullFrontal 2009 onto developer’s forum at work. And one full colleague of mine enquired why did I say that “javascript:void(0)
must die”. I didn’t really have a chance to follow it up until now (happy birthday, dear blog).
It doesn’t do anything, it just sits there!
Now, normally I’m not a complete standards freak (unlike the guys working on Caja). But what does <a href="javascript:void(0)">
really mean? The answer is simple – nothing.
First of, it’s a hyperlink to a resource, which should be accessed over Javascript “protocol”. Here’s the problem – I don’t really feel that “javascript” is a protocol. And it can’t really handle resources. But lets ignore that. What is the actual resource?
The link tells “use javascript” to “retrieve”… void. Why would anyone in the world want to view void in their browser? If anyone ever wants to look at it – they’re much better off achieving that goal on YouTube…
Semantics apart – it’s not comprehensible
Lets suppose, you don’t really care about web standards and semantics. I’d probably agree with you – we’re quite far away from having a meaningful web (if ever). Still, having crap as the URL is no good – apparently, screen readers will read that URL out loud.
Can you imagine anyone discussing this over a pint: “You know, I found this great site at javascript colon void opening parenthesis zero closing parenthesis“? That kind of URL would not make any sense to regular folks.
Accessibility is NOT about screen readers, though
Such a link kills browsing experience for sighted users too. Have you ever tried what happens when you middle-click the void link? Or right-click and then select “Open in new tab”? Here – try it out (mileage may vary if you use a recent browser).
Exactly – you guessed it – nothing meaningful happens. Just as it should!
Solution 1: Use real URLs
There are several ways out of this. My favorite one is to provide a real URL. If you’re following progressive enhancement methodology in your work, you always want to provide alternative links to achieve (near full) functionality even when Javascript is disabled.
This means, that instead of having a <a href="javascript:void(0)">Delete</a>
and attaching onclick
handler to it, popping out a confirm dialog and then making a background call using XHR, you provide a link to e.g. /myResource?delete
which brings up a form, with a real <button>
.
The actual backend code doesn’t become that much trickier – you don’t really have to write up a new “delete” routine. By using a confirmation interstitial, you also provide a way to confirm the action, and you can still use a POST request, as this action has permanent effect.
Solution 2: don’t use anchor tag
The above solution doesn’t always work – if you have a really interactive application, you’re not always able to provide links. However, since you’re already using JS – why use the <a>
tag where it doesn’t belong?
I did hear some advice, to use <button>
for clickable things, which are not really links. You should investigate that, but anyone who has tried to style buttons, knows that it can very easily become a major pain.
Still, you can attach your onclick
handlers on anything you want – div
, span
and so on. In such cases, you should also add tabindex
to make elements focusable and make use of ARIA roles to provide guidelines on behaviour. It’s not really that hard, now, is it?
The only really painful thing here is providing :hover
and :focus
styles on IE6. But IE6 should also die, together with javascript:void(0)
.
3 Responses to “javascript:void(0) must die”
Comment RSSUsing real URL’s is great as long as you have built that into your design from the start. You should probably mention that using GET’s to update/delete is probably not a good thing – which people might implement while taking a short-cut.
Redirecting to a new form from the link to support regressive dehancement ;) is my favourite choice, also links are crawlable, URL’s don’t need to be maintained in server-side AND javascript etc. – but it means more coding, and the client won’t pay for that (time, not necessarily money). But that opens up the whole question of selling basic functionality to the business, which is always a hard sell – “gimme what I want, not what I need”
Mark, even if you hadn’t provided real URLs from the start, you can always link to named anchors, i.e. #something – as long as #something exists (even a div with an id will do) – it’s better than void. Forgot to include that in the post :)
I did, indeed, not elaborate on the whole GET/POST topic – but hey – it’s for future use :) Especially if I get a chance to publish the security slides.
As for redirecting to a new form – the same URL can handle both AJAX, and non-AJAX (/myResource?delete=yes&confirmed=yes). Assuming you’re already doing a POST, you just need to check for AJAX header and return appropriate view – be it MVC or not – if (AJAX) { echo JSON() } else { echo HTML() } – not that much code required!
The only real thing to build is the “interstitial form” – but that can easily be frameworkified. In reality, supporting this is not even 10% overhead on individual feature, compared to the hoops that you have to implement for it to work (access checking, validation, escaping, connections, etc etc). And it’s even more negligible in the big picture of the overall project (whatever the case may be) – you need frameworks developed, etc etc.
There’s no reason to be lazy, whether client pays for it or not. If one starts doing that now, and charging their customers 5% more, without even negotiating the “accessibility” aspect – the “just do it” way – it’s still just just more than inflation in Ireland in 2008. And you get the bragging rights as well, even if the customer doesn’t realize that :)
Right on. We use a tags with href=”#action_name” at webdoc.com – and that’s because I have been bitten by button style before. I haven’t tested them in a year, but back when I did FireFox was the culprit – it was impossible to remove overflow: hidden, among other things, I seem to remember.
Anyway, at some point I’m going to move our buttons to being command tags, the new html5 element for application commands. In the spec, it appears you can replace li tags in a ul or menu with command tags, which is pretty groovy.