Thursday, April 25, 2013

Ask A11y Volume 1

About A11y:  I answer a lot of questions about Web accessibility best practices at my job, so thought I would bring some of those topics online for the larger community. 

Dear A11y,

As a web developer, I'm trying to practice progressive enhancement. A lot of the time, I receive specs that have a link that kicks off a JavaScript interaction when clicked. However, often these links don't have any logical landing URL. Is it better to use <a href="#">Link</a> or <a href="javascript:void(0);">Link</a> in this situation?

Signed,
Progressive in California

Dear Progressive,

Both suggestions have practical and accessibility issues. First, on the practical side, <a href="#"> will cause a hashchange event unless you also prevent the default behaviour of the click event in your JavaScript. This can cause issues with single-page-apps that use hashchange events for routing. Also, if the user is scrolled down the page, it will have the result scrolling to the top. If you use <a href="javascript:void(0);">, the anchor now has a return value of undefined, which can open you up to security issues. That should be reason enough not to do it, though it does not suffer the hashchange or scrolling concerns. HTML requires us to provide an href attribute on an anchor in order to be valid. In order for non-sighted users to not anticipate linking behaviour, we can use a role="button" attribute to set the expectations for the link. However, adding role="button" does not change the HTML Node Object type from an anchor to a button, so the spurious href attributes are still required, which brings us back to the practical issues.

So, the answer to your question is: neither. In my opinion, the semantic and accessible solution is to use a <button> element for these behaviours. The button element does not have the href attribute situation and properly sets expectations for all users. There are some practical concerns when using buttons, especially if you plan for them to appear as links on the page. This can be handled in the CSS layer, which also gives you a proper separation between meaning (markup), presentation (CSS), and interaction (JavaScript).

Here is how the situation can be resolved:

<button class="link">Link</button>

button.link {
  background:none;
  border:none;
  padding:0;
  appearance:none;
  -moz-appearance:none; /* Firefox */
  -webkit-appearance:none; /* Safari and Chrome */
  color:blue;
  text-decoration:underline;
}


Or, if you are using SASS and Compass as we are in our workplace, you can do the following:


@mixin link {
  color:blue;
  text-decoration:underline;
}
@mixin unstyled-button {
   background:none;
  border:none;
  padding:0;
  @include appearance(none);
}

button.link {
  @include unstyled-button(); /* removes button styling */
  @include link(); /* applies link styling */
}

Happy button-making!

-A11y

No comments: