Valid to use <a> (anchor tag) without href attribute?

Zacqary picture Zacqary · May 9, 2012 · Viewed 165.4k times · Source

I've been using Twitter Bootstrap to build a site, and a lot of its functionality depends on wrapping things in <a>, even if they're just going to execute Javascript. I've had problems with the href="#" tactic that Bootstrap's documentation recommends, so I was trying to find a different solution.

But then I tried just removing the href attribute altogether. I've been using <a class='bunch of classes' data-whatever='data'>, and having Javascript handle the rest. And it works.

Yet something's telling me I shouldn't be doing this. Right? I mean, technically <a> is supposed to be a link to something, but I'm not entirely sure why this is a problem. Or is it?

Answer

zzzzBov picture zzzzBov · May 9, 2012

The <a>nchor element is simply an anchor to or from some content. Originally the HTML specification allowed for named anchors (<a name="foo">) and linked anchors (<a href="#foo">).

The named anchor format is less commonly used, as the fragment identifier is now used to specify an [id] attribute (although for backwards compatibility you can still specify [name] attributes). An <a> element without an [href] attribute is still valid.

As far as semantics and styling is concerned, the <a> element isn't a link (:link) unless it has an [href] attribute. A side-effect of this is that an <a> element without [href] won't be in the tabbing order by default.

The real question is whether the <a> element alone is an appropriate representation of a <button>. On a semantic level, there is a distinct difference between a link and a button.

A button is something that when clicked causes an action to occur.

A link is a button that causes a change in navigation in the current document. The navigation that occurs could be moving within the document in the case of fragment identifiers (#foo) or moving to a new document in the case of urls (/bar).

As links are a special type of button, they have often had their actions overridden to perform alternative functions. Continuing to use an anchor as a button is ok from a consistency standpoint, although it's not quite accurate semantically.

If you're concerned about the semantics and accessibility of using an <a> element (or <span>, or <div>) as a button, you should add the following attributes:

<a role="button" tabindex="0" ...>...</a>

The button role tells the user that the particular element is being treated as a button as an override for whatever semantics the underlying element may have had.

For <span> and <div> elements, you may want to add JavaScript key listeners for Space or Enter to trigger the click event. <a href> and <button> elements do this by default, but non-button elements do not. Sometimes it makes more sense to bind the click trigger to a different key. For example, a "help" button in a web app might be bound to F1.