Links vs. JavaScript Event Handlers

Anchor tags are frequently used to do something other than what they were meant for, such as executing some JavaScript code.  I’m talking about cases such as these:

<a href="javascript:doSomething()">Click Here</a>

// or...
<a href="javascript:void(0)" onclick="doSomething()">Click Here</a>

Both of these are bad practice and should be avoided.  The purpose of the anchor tag is to provide a link to a separate page so that the its interpreter (human or program, such as a search crawler) can use the value of its HREF attribute to reach another page (URL).  If what you are putting into the HREF attribute is not a valid URL, you’re very likely using the wrong tag.

A similar example of anchor misuse is specifying an empty fragment identifier:

<a onclick="doSomething()" href="#">Click Here</a>

// and another...
<a id="someLink" href="#">Click Here</a>
<script type="text/javascript">document.getElementById("someLink").onclick=doSomething;</script>

Again, in these cases the HREF tag doesn’t lead to another page which means that the tag is used improperly.

What tags should you use instead?

If the HREF leads to another page (URL), use the anchor tag and point the HREF at it.  Otherwise, use a different, more appropriate tag to display your element, and then assign a handler to it.  Here’s a simple example:

<button id="click">Click Me</button>
<script type="text/javascript">
document.getElementById("click").onclick = function(){ alert("clicked!"); }
</script>

// or...
<input type="image" id="buttonEdit" src="/buttons/edit.gif"/>
<script type="text/javascript">document.getElementById("buttonEdit").onclick=doEdit;</script>

// or even...
<div id="doer">Click Here</div>
<script type="text/javascript">document.getElementById("doer").onclick=doSomething;</script>

You can create CSS rules to assign the desired hover cursor, etc.  (By the way, when you discover that Internet Explorer 6 doesn’t like CSS hover assignments for non-anchor elements, you should use jQuery’s hover() method to do that instead or find other ways around it.)

“Button” tags are severely severely under-used, in my experience, and they’re ver appropriate for modern ajax-based applications.  If your app requires a form, using an INPUT tag to submit is always a better choice than using an anchor, and particularly so if no page refresh is involved.  As for using other tags, such as DIVs, you might say that DIV tags weren’t intended for action buttons either, and you’d be correct.  But depending on the implementation they might be just want you want and since all standard handlers (click, mouse over/out, blur, focus, etc.) are supported by default, its not actually wrong to use them.  And yes, the anchor tag supports those same handlers, but they always conflict with its special, and required HREF attribute and resolving that conflict is hackish and could lead to problems.

(Obviously, in each code snipped above the scripts should be separated from the markup.)

Are there exceptions?  Of course.

The fragment identifier (the “#…” HREF value) has a very important and useful purpose: to go (generally, to scroll) to a section of the current page.  In this case, the HREF doesn’t point at a separate URL, which is actually a very handy feature since the URL (in browser’s address bar) is updated, but the page isn’t refreshed.  Many applications make use of this feature to allow bookmarking sections of a page, or even more cleverly, to update the URL of the page depending on its ‘state’.  Applications which make use of this technique are pretty common nowdays, but one which immediately comes to mind is Google’s Gmail, which maintains the original URL but keeps track of the current state (inbox, compose, etc.) through use of fragment identifiers.

There are other scenarios where anchor tags might be the best choice, but before you start hacking your HREFs, make sure there isn’t a better option.