Grow your CSS skills. Land your dream job.

When (and when not to) use an anchor tag?

Published by Chris Coyier

Interesting question from reader Don Wilson:

I'm curious to know your opinion. When should we use anchor tags and when should we use something else?

I have generally used the `a` tag liberally whenever I wanted something to be clickable. I looked up the definition and it appears that I am using the `a` tag where it is not meant to be used. I looked through the GMail source and they are using `div` elements for most of their clickable things.

I think that my usage has come from writing HTML from before Javascript was widely used for events. Anyways, I'm not sure now where I should draw the line for the `a` tag. What's your opinion?

I think if you are going to put a href attribute on the anchor that actually does something even if JavaScript is disabled, then the anchor is the right choice. If the app is totally JavaScript dependent all behavior is attached via JavaScript, I guess it doesn't really matter what element you use. Maybe it's even better not to use an anchor since the behavior probably bears no resemblance to what anchor links do. You could probably talk me out of that though. The thing is, anchors give you ("for free") lots of the visual functionality that you want with deep browser support. So...

If you chose not to use anchor links for clickable functional elements, then:

  • Use cursor: pointer; so users get the cursor that looks like you can click like they are used to.
  • Use the tabindex attribute on the element so keyboard users can tab to it.
  • Define :hover, :active, and :focus styles.

View Demo

Comments

  1. I think the button element is best suited for JavaScript interaction. They’re fairly customizable and you can even make them look like links.

    My only issue with using elements besides anchors or buttons is that they cannot be focused by the keyboard. The tabindex attribute isn’t all that great because you have to provide a value, and so you’d basically have to add a tabindex attribute to every single focusable element if you want to make the page act the way it should.

    It’d be nice to have something like a “focusable” attribute, or have tabindex work without a specific value. This would prevent people doing stuff like <a href="#">click me</a> or even <a href="javascript:void(0)">click me</a>. If you can though, please use the button element as that makes the most sense.

    • Kevin
      Permalink to comment#

      Sorry, didn’t read your full comment before I added my own. You already pointed it out, focusability.

    • Mark
      Permalink to comment#

      Regarding: “you have to provide a value, and so you’d basically have to add a tabindex attribute to every single focusable element”

      That is not quite how it works. tabindex=”0″ is equivalent to not specifying an attr/value pair, but it serves to bring an element into the tab index. Therefore, one does not need to alter tab order (which is very inadvisable anyway) in order to bring an element into the tab index.

    • lel
      Permalink to comment#

      @mark Great tip on the tabindex=”0″!

      This discussion encourages me to consider more carefully where I use the anchor tag.

    • @Mark: There seems to be a bug in IE8 with tabindex="0". Any element with this attribute is focused right away.

      http://fiddle.jshell.net/TdeZc/1/show/light/

  2. Kevin
    Permalink to comment#

    Anchors are focusable, that’s why they’re used even when “all behavior is attached via JavaScript”.

  3. Permalink to comment#

    using DIVs or SPANs on non-link is great since you do not need to prevent default in the onclick.

  4. How about the good ol’ <button>? Built-in hover (maybe just on Win), focus, and active statuses and no need for tab-index.

  5. Some guy
    Permalink to comment#

    I prefer to use anchors because you may bookmark dfferent states (for example, sitename#about, sitename#portfolio), while you can’t do that if you use div-s for that.

    anchor tag is also more semantic and better recognizable in code than div.

  6. Permalink to comment#

    I’m all against setting cursor to “pointer” for all clickable elements.
    WebApp IMO is more an “app” and less a “website” therefore only actual links are supposed to have “pointer” and all other actions/buttons – “default”.
    And it looks much cleaner too :-)

    • I prefer having “cursor: pointer;” on buttons and all clickable elements, just because it’s what I’m comfortable with. It makes me feel like it’s actually going to do something when you click it. :)

  7. I always use anchor tags because some IE versions (big surprise!) does not support :hover on div elements

  8. Brendan
    Permalink to comment#

    I avoid using anchors unless they are specifically for navigating to another page. Even then, I usually wrap Javascript around the click event due to weirdness on the iPad in fullscreen mode.

    My normal ‘clickable-but-probably-fires-some-event-rather-than-navigation’ html looks like this usually:

    <span class=”clickable” data-target-id=”someIdentifier”>Some descriptive text<span>

    …I apply styles to .clickable to make it visually look like a link. I don’t like having to deal with e.preventDefault(); everywhere I want a clickable element. The argument in this case I would expect would be “well what happens if they have Javascript turned off?”. Nothing. Too bad. Turn Javascript on. I don’t write tons of fragmented pages to handle functionality that is better handled in a dialog, flyout, etc. I consistently use the same classname throughout projects, so the hardest part is opening up a previous project and copying out my commonly used classes.

    That said, I don’t write web-”sites” as much as applications, and lots of prototypes that need to be in a demo-able state on very short notice… perhaps if I was writing for more general consumption I would feel differently.

  9. Jesse
    Permalink to comment#

    I say anchors. Shouldn’t javascript heavy apps have the appropriate non-javascript fall backs? You get that with anchors (assuming you don’t neglect your href), you don’t with divs.

  10. Permalink to comment#

    Yep, if you are using <a href="">, it must point to something real. Since JS can be turned off or blocked by a proxy/firewall/ad-blocker or fail due to some network error, user can open a link in new window or tab, copy address and do everything else what he or she can do with link. If you are using buttons, it’s good idea to use forms to make it work without JS too whenever it’s possible.

  11. Jeff K
    Permalink to comment#

    Regarding the “what if Javascript is turned off” argument, I believe that is a valid argument for web-sites. And in that case anchors should be used, and should navigate somewhere useful in the event that Javascript is off.

    But I think we are at a point where we can say, for web-apps, that Javascript must be on, and that if it is off, the app won’t work. So I see nothing wrong with relying on Javascript to perform an action or navigate somewhere.

    I do agree with the focusable argument. We can’t tabindex everything. You would need to re-index each time an element was added to the page. A focusable property would be great! For now, where I want the user to be able to tab, I will use anchor. If I don’t require the user to be able to tab there (because I’m implementing another way of using the keyboard to activate the element) then I will consider div’s etc.

  12. In the current javascript-only web-app I am working on I use anchors with href="#name_of_the_action" everywhere and in some cases I even parse the href-attribute via javascript to determine the function to call.

    But just a few days ago I thought about replacing all this stuff with buttons. This discussion just confirmed my plan.

  13. jen
    Permalink to comment#

    I’m a proponent of using anchors for toggle events, and it seems the mid- & back-layer developers on my team prefer using form elements. I don’t understand this, at all, and haven’t received a satisfying response. From this post, it appears that anchors are still the most appropriate solution. Actually, a button might be a suitable option for the item in question, too. I’ll propose that tomorrow. It’s still not a form, anyway, and a lot more straightforward to style, plus more semantic than a form with a ton of hidden inputs.

  14. I suggest a in-page-action <a> tag should be defined as a link (or anchor) in the current page. For example, set the HTML code:

    <a id="btn-show-panel-x" href="#show-panel-x">Show</a>

    and the JavaScript:

    $('#btn-show-panel-x').click(function (e) {
        e.preventDefault();
        // TODO show panel x ...
    });

    Than we can see some friendly information in the status bar when mouse over the anchor, and we can also use the anchor styles at the same time.

    In addition, I also use <button> tag quite open to for “clickable” meaning. But the styles is a problem.

    <div> tag have no semantic meaning else. Does it appropriate?

  15. I think its really all about the behaviour that follows… In a semantic point of view i would use anchor tags only if there is really a hyperrefference attached to it. So if there is a page reload happening or something similar i would totally go for it, otherwise you can still use a span element.

  16. First of all Chris, thanks for responding to my question. This has been a cool experience to see your reply and for this great discussion on this topic.

    In my app I have definitely resorted to certain functionality just not working if JavaScript isn’t enabled. So, I find myself naturally putting ‘junk’ in the href attribute (eg. href='#' or href='javascript:void(0)'). Then, when I read the definition for the a tag, these use cases seemed to be entirely not semantic at all.

    I think that Chris’s suggestion really makes sense. It is kind of fun to change my way of doing things. I had an unordered list that just contained an anchor tag with href='javascript:void(0) in each li element that was being set to display:block. I changed that so that the li elements themselves were clickable. It actually turned out to be a lot simpler.

    • Am I missing something? How did *you* made li to be clickable? I thought *every* element is clickable already :)

      The problem is that, by default, only the anchor element has a distinct clickable look and behavior that users recognize and browsers follow.

      Otherwise, it just takes a bit of JS code.

      One more thing. You need to be in the habit of providing a progressive enhancement, web site or we app, as a good programming technique.

      With that, I’m saying you’re not doing it right by using just the naked li elements.

    • Sorry, I meant focusable, not clickable.

      I totally support progressive enhancement/graceful degradation and I am always thinking about that. However, on the topic of JavaScript, I think there is a totally valid argument for certain websites/webapps to require it to be enabled. For example, Facebook requires it unless you use the mobile version of their website.

    • I think the truth is somewhere in the middle, about required JS support from the user.

      If the name is big enough, it can dictate the terms and forget about a few whiners. But I see this stance as detrimental.

      From what I experience, Google made the right choices, going basic to start with, then pretty and enhanced for those willing to experience a full blown interface.

  17. Keyamoon
    Permalink to comment#

    Google page speed docs state that you should “Avoid the :hover pseudo-selector for non-link elements for IE clients.”

    http://code.google.com/speed/page-speed/docs/rendering.html

    Well, on the other hand, gmail is unig divs!

    But I still would prefer anchor tags.

  18. Anchors = www world wormholes. Connecting two points in local or remote HTML web pages space. Even when JS is not available.

    Otherwise, I agree with Chris and Google. If it’s web apps we talk about, any clickable element and their mother will do: input, button, div, span etc.

    Though I have to say it’s a progressive enhancement we’re talking about. Some web apps, like Google Translate, GMail will work even w/o JS.

  19. Mike Hopley
    Permalink to comment#

    Definitely use a <button>, because it means “this will invoke an action”. A link (<a>) means “this is a hyperlink. It will take you to another page/resource”.

    Never choose the element based on its default styling. This is no different from (say) using <h2> for top-level headings because “the font is too big when I use an <h1>”. You can easily make buttons look like links, if that’s what you want.

    And if you must use the wrong element, at least throw a bone to screenreaders and add role="button", as TJ Crowder mentioned.

    See this video from YUI Theater: Common Accessibility Mistakes

    Quote from 14:50 in:

    When you have a button, it basically tells the screen-reader that this is an action. It’s an action that’s going to create something, it’s gonna change something. But it’s not necessarily gonna take me to a new page.

    When I have a link, a link says “I’m gonna go to a new page.”; and so it’s gonna tell me where is that page.

    So if you have a button to do a sign-in, but a link to cancel, that link is actually confusing to the screen-reader because the “cancel” is not another page, it’s an action.

    So use a button for any of your actions, not a link. … Don’t confuse functionality with design. If they have a button and a link in the interface, you can still use a <button> for both.

    Now if you have a tonne of these things on your site, and you don’t have time to go back in there and redesign all your javascript and all your code, what you can do is use a little bit of an ARIA role … role="button". And that’s an attribute you can put on a link. This isn’t a great way of fixing it, but at least tells the screen-reader that “this is a button. It’s not a link”. So at least the expectation will be different.

    Ideally what you do is use the button in the first place.

    • “When I have a link, a link says “I’m gonna go to a new page.”; and so it’s gonna tell me where is that page.”

      I don’t know about this. There are some nuances here to be noted.

      The <a> element is what he means by link, but link means more: <area>, <link>.

      And <a>, as an interactive content element, can point to a resource on the same page.

      Excerpts for the specs:

      “Links are a conceptual construct, created by a, area, and link elements [...]

      There are two kinds of links in HTML:

      Links to external resources[...]
      Hyperlinks[...]
      If the a element has an href attribute, then it represents a hyperlink (a hypertext anchor).

      If the a element has no href attribute, then the element represents a placeholder for where a link might otherwise have been placed, if it had been relevant.[...]

      If a site uses a consistent navigation toolbar on every page, then the link that would normally link to the page itself could be marked up using an a element:
      <li> <a>Examples</a> </li>

      Notice the missing href attribute.

    • Mike Hopley
      Permalink to comment#

      Yes, there are nuances — such as links jumping to somewhere else on the same page (i.e. in-page navigation).

      None of the nuance changes the essential nature of a link, or of a button:

      – Links are “go somewhere” interfaces
      – Buttons are “do something” interfaces

    • - Links are “go somewhere” or “go somewhere and get something”.

      Otherwise, it’s true what you’re saying.

  20. Ray
    Permalink to comment#

    Does div:hover work on IE6?

  21. Great discussion folks!

    Here’s more thought by Ryan Fitzer: http://ryanfitzer.org/2011/08/to-be-or-not-to-be-an-anchor/

  22. Evan
    Permalink to comment#

    I used to anchors way too often trying to get :hover support out of ie6 on elements that were not actually linking anywhere.

    Now that I don’t have to worry about ie6 I don’t ever do this.

  23. What about <command> tag? It’s not supported for all browser, but maybe it will be good solution for this problem.

  24. Permalink to comment#

    I will prefer to use anchor tags because some browsers behave differently for events on div tag.

  25. Alright,
    I see a lot of valid points but what do you do when you’re building an HTML/JS audio player vs. a flash audio player. For example, I’m currently developing a UI for a client web app, and one page has a audio player element that will play voice messages. It has a Play/Pause button, previous message and next message buttons, as well as a message elapsed/total time display. It also has a search field for searching for a specific message.

    I’m currently using this code to mark it up, but to me it doesn’t feel write, and then there are also the box model issues with the <button> tag.

    
    <div id="message_player">
      <form action="" method="get">
        <div id="controls">
          <div id="play-pause_msg"><button type="button"><img src="images/play.png" alt="Play"></button></div>
          <div id="previous_msg"><button type="button"><img src="images/previous.png" alt="Previous"></button></div>
          <div id="next_msg"><button type="button"><img src="images/next.png" alt="Next"></button></div>
        </div>
        <div id="message_status">
          <p>Wed Jul 3, 2011 @ 1:44PM</p>
          <span id="message_elapsed">0:00</span>
          <div id="duration_bar"></div>
          <span id="message_length">0:00</span>
        </div>
        <div id="message_search"><input id="messageSearch" name="messageSearch" type="text"></div>
      </form>
    </div>
    
    

    I had changed the markup a few times, initially using <a> tags, then <div> tags, and finally after doing more searching and reading a few articles/posts I landed at <button>.

    What would I be best off doing, because for me it’s a constant battle in my mind over which is the RIGHT way to do it. Accessibility is less of an issue due to the fact that our client’s target demographic for the app will be MD’s.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".