Anchor tags versus buttons

It all started with a tweet by Steve Faulkner.

By that time I had asked myself this question several times inspecting the ways gmail was coded. It also sort of combined in my head with another question. Why do people use <a> elements to trigger some javascript magic? Inserting a href="#" or even more crap-like: href="javascript:void(0)". So how do we generally identify that something is a link and something is a button?

I saw a suggestion somewhere that buttons do things while anchors go to places. Which is kinda nice and logical, I think. In most cases… Later on Chris Coyier came up with an excellent article on the topic. His idea that if a button doesn’t have a meaningful href, it’s a <button> also holds true and can identify the true buttons and links. The only things that I disagreed on were his examples of true links.

So here I go with some more real-life examples in addition to Chris’s.

I will try to compare each example against both ideas: buttons do things while anchors go to places and if a button doesn’t have a meaningful href, it’s a <button>. Additionally, we’ll see if we can have access to the content if we have only keyboard.

1. Accordion

As an example of an accordion I will take an F.A.Q. section that opens the answer when a user clicks a question. A typical markup for this will be a description list.

    <dt>Question 1</dt>
    <dd>Answer 1</dd>
    <dt>Question 2</dt>
    <dd>Answer 2</dd>
    <dt>Question 3</dt>
    <dd>Answer 3</dd>

No matter if javascript is enabled or not we don’t have the ability to navigate between questions via keyboard. The content is fully accessible with no javascript.

To correct the issue of keyboard navigation we may add the tabindex attribute. It does not need to have a different value for every single question. It may be the same, for instance tabindex="1". In this case such elements will be navigated in accordance with the order they appear. Although simply navigating the questions will do us no good since we can’t open any answer without modifying our javascript. So by adding another event listener and checking the keyCode of the bar that was pressed we can achieve what we want.

1.1. buttons do things, and we do “open” an answer, right?

Let’s enhance our code progressively via javascript to look like so:

    <dt><button type="button">Question 1</button></dt>
    <dd>Answer 1</dd>
    <dt><button type="button">Question 2</button></dt>
    <dd>Answer 2</dd>
    <dt><button type="button">Question 3</button></dt>
    <dd>Answer 3</dd>

What do we have here? A native ability to navigate between the questions via keyboard. Requires no keypress event handlers because pressing the space bar or the enter bar triggers the click event. And if javascript fails a user will be able to access all of the content with ease. Feels far better now.

1.2. Can a question have a meaningful href?

Sure. In this case the initial html should be something like this:

    <dt><a href="#answer1" tabindex="1">Question 1</a></dt>
    <dd id="answer1">Answer 1</dd>
    <dt><a href="#answer2" tabindex="1">Question 2</a></dt>
    <dd id="answer2">Answer 2</dd>
    <dt><a href="#answer3" tabindex="1">Question 3</a></dt>
    <dd id="answer3">Answer 3</dd>

What is important to notice is that anchor tags trigger the click event only when pressing the enter button, and not the space (unlike <button>s do). If you want to include pressing this button (as you should) you will need to modify the script a bit.

As an additional bonus of this method goes the ability to provide a direct link to a specific answer, which is great if we have a big number of questions.
A slight technical variation of this will be to include the id attribute to the anchor element itself. Thus the question will be visible to the user too. Although it will be of almost no use as the answers are hidden by default. So it will be wise to check our URL for a hash value on page load and if it corresponds to one of the questions we will make its answer open.

I don’t get it at all, how shall I code?

I come to the conclusion that the first and the third variants are perfectly valid and semantic. The second variant does not improve semantics and does not break it. It actually does nothing to semantics whatsoever. It only improves the accessibility of our content.

In the end it comes down to what functionality you need (are ready) to provide. In my opinion the last variant (adding additional anchor tags, attributes, keyCode and hash checks) has everything you need.

2. Tabs.

Although again it may look like we “switch tabs” and do not link to them, the <a> brings more benefits than the <button>. I won’t go into much detail about this as it is very similar to my previous example.

In the end, let me provide a couple of examples where <button> tags are preferable, to my mind.

  1. next/prev buttons in either a carousel, or in a popup photo gallery.
  2. Buttons that control the behavior of a carousel or a gallery (like “start the automatic rotation”).
  3. “X” that closes a popup, or any other button that somehow modifies it (e.g. a “full-screen” button)
  4. “Copy to clipboard” button
  5. “increase the font-size” button
  6. any “Cancel” button
  7. “Load some more posts” button
  8. “Hide/minify the comments” button

and so on.

…see the pattern? We cannot even say “Copy to clipboard” link, or “Hide the comments” link. As they are no links.


It looks like my examples work for Chris’s statement that if we can conjure up a meaningful href we will have both semantics and functionality even if it looks like we “do things”.